web-dev-qa-db-fra.com

React - Créez des composants imbriqués avec des boucles

J'ai un petit problème avec React. Je ne peux pas créer de composant imbriqué avec une boucle for. Ce que je veux faire, c'est créer 9 cellules d'un tableau, puis créer 3 lignes avec 3 cellules pour chaque ligne, puis monter les 3 lignes ensemble et créer un tableau 9x9.

Disons que je veux obtenir quelque chose comme ça, mais en utilisant une boucle

class Board extends React.Component {     
renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}

render(){    
    return(
        <div>
            <div className="board-row">
                {this.renderSquare(0)}
                {this.renderSquare(1)}
                {this.renderSquare(2)}
            </div>
            <div className="board-row">
                {this.renderSquare(3)}
                {this.renderSquare(4)}
                {this.renderSquare(5)}
            </div>
            <div className="board-row">
                {this.renderSquare(6)}
                {this.renderSquare(7)}
                {this.renderSquare(8)}
            </div>
        </div>
    );        
}

}

J'ai cherché d'autres personnes pendant des heures et je pense que mon code est presque correct mais il ne rend pas ce que je veux. Je ne reçois qu'une page blanche.

voici mon code:

class Board extends React.Component { 

renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />;
}

createCells(i){
    if(i%3){return;}
    var index = this.fillN(Array(i)); //index=[0,1,2,3,4,5,6,7,8]
    var cells = [];
    index.forEach(function(i){
        cells.Push(() => {
            return(
                <div>
                    {this.renderSquare(i)}
                </div>
            );
        });
    });
    return cells;
}

createRows(cells){
    var index = this.fillMod3(Array(3)); //index=[0,3,6]
    var rows = []
    index.forEach(function(i){
        rows.Push(() => {
            return(
                <div>
                    {cells[i]}
                    {cells[i+1]}
                    {cells[i+2]}
                </div>
            );
        });
    });
    return rows;
}

render(){    
    var cells = this.createCells(9);
    var rows = this.createRows(cells);
    var board = [];
    var index = this.fillN(Array(1));

    index.forEach(function(row){
        board.Push(() => {
            return(
                <div>{row}</div>
            );
        });
    })

    return(
        <div>
            {board[0]}
        </div>
    );        
}

J'ai toujours sur l'écran quelque chose comme ça:

<Board>
  <div> /*empty*/ </div>
</Board>

Je tiens à préciser que je suis sûr que le reste du code avec lequel ce composant (Board) interagit n'a pas de problèmes.

Je suis nouveau en réaction et si someoane peut m'aider, j'apprécierai beaucoup ..__ Désolé pour mon anglais médiocre

EDIT1: Suivant marklew examples je devrais être capable de faire quelque chose comme ça 

    render(){   
    var index1 = this.fillN(Array(3)); //index1=[0,1,2]
    var index2 = this.fillN(Array(3)); //index2=[0,1,2]

    return(
        <div>
            {index1.map((e1,i1) => {
                return(
                    <div key={i1} className="board-row">
                        {index2.map((e2, i2) => {
                            return(
                                <p key={i2+10}>
                                    {this.renderSquare(i2)}
                                </p>
                            )
                        })}
                    </div>
                )    
            })}
        </div>
    );

}

mais ça ne fait pas ce que je veux. J'obtiens juste une colonne avec 9 cellules et les cellules sont les mêmes objets. Je ne comprends pas pourquoi. (Je comprends que ce sont les mêmes objets parce que j’assigne une fonction de traitement onClick quand je les crée comme ça:

<Board 
     onClick={(i) => this.handleClick(i)} //handleClick just draws a X in the cell
     />

et je reçois le X se noyer dans 3 cellules simultanément

EDIT2: Je suis arrivé à une solution:

render(){   
    var index1 = this.fillMod3(Array(3));        

    return(
        <div>
            {index1.map((e,i) => {
                return(
                    <div key={i} className="board-row">
                        {this.renderSquare(e)}
                        {this.renderSquare(e+1)}
                        {this.renderSquare(e+2)}
                    </div>
                )    
            })}
        </div>
    );

}

}

mais ce n'est pas ce que je veux. Je veux une autre boucle, même pour la fonction renderSquare (i) interne.

8
neboduus

Pour rendre une liste d'éléments dans JSX, vous pouvez faire quelque chose comme ça:

render() {
    return <div>
        {
            [1,2,3].map ( (n) => {
                return this.renderSquare(n)
            })

        }
    </div>;
}   

Enveloppez simplement votre tableau de composants dans {} dans votre JSX.

Pour clarifier un peu, c'est la même logique de:

return <div>
    {
        [
            <h1 key="1">Hello 1</h1>,
            <h1 key="2">Hello 2</h1>,
            <h1 key="3">Hello 3</h1>
        ]           
    }
</div>;

Notez que chaque fois que vous rendez un tableau de composants, vous devez fournir un prop key, comme indiqué ici .

En outre, si vous souhaitez simplement imprimer la valeur de la ligne dans votre fonction de rendu, vous devez remplacer:

index.forEach(function(row){
    board.Push(() => {
        return(
            <div>{row}</div>
        );
    });
})

avec:

index.forEach( (row, index) => {
    board.Push(<div key={index}>{row}</div>)
})

ou encore, en remplaçant forEach et Push par map:

board = index.map( (row, index) => <div key={index}>{row}</div> )

EDIT J'ai créé un violon avec un tableau 9x9 en utilisant votre code comme base: https://jsfiddle.net/mrlew/cLbyyL27/ _ (vous pouvez cliquer sur la cellule pour le sélectionner. )

12
mrlew

Je vois que vous aussi suivez le didacticiel JS React! Voici ce que j'ai fait, mais j'y travaille car il doit y avoir un bon moyen de donner à chacune de ces clés.

J'ai rencontré le même problème que vous rencontriez lorsque les X ont été dessinés dans 3 carrés, et la raison en est que parce que lorsque vous rendiez des carrés, certains des "i" étaient dupliqués. Donc, il y avait plusieurs carrés avec le "i" de 2 par exemple (du moins c'était le cas dans mon numéro). 

Donc chaque carré a un index non? [0,1,2,3,4,5,6,7,8].

Nous devons d’abord trouver comment les mettre en relation de manière à pouvoir les rendre en rangées! Ainsi, dans votre exemple, vous avez index1 et index2, qui, je suppose, feront référence aux coordonnées x et y du carré du tableau. En réécrivant le tableau ci-dessus, nous arrivons à: [{0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0, 2}, {1,2}, {2,2}] en utilisant le format {x, y}. Comment pouvons-nous utiliser ces valeurs (que nous obtiendrions de vos index1 et index2 afin d'obtenir le tableau de valeurs d'origine que nous avons commencé avec [0,1,2,3,4,5,6,7,8]?

Ce que j'ai fait était 3 * x + y (ou dans une boucle, 3 * i + j). De cette façon, chaque carré est associé à une valeur "i" unique.

Après avoir configuré mes boucles, j’ai utilisé this SO pour renvoyer correctement les éléments que j’ai créés à partir d’une fonction distincte (dans une tentative médiocre de garder mon code plus propre). 

C'est ce que j'ai fini avec, mais je dois m'assurer que les clés sont correctement définies, ce qui est en fait la façon dont je suis tombé sur ce message:

createSquares() {
  let rows = [];
  for(var i = 0; i < 3; i++){
    let squares = [];
    for(var j = 0; j < 3; j++){
      squares.Push(this.renderSquare(3*i+j));
    }
    rows.Push(<div className="board-row">{squares}</div>);
  }
  return rows;
}

Ensuite, ma fonction de rendu dans Board ressemble à ceci:

render() {
  return (
    <div>
      {this.createSquares()}
    </div>
  );
}
4
mrzepka

Voici le meilleur que je puisse penser après avoir lu les réponses ici et dans Loop dans React JSX :

  render() {
    return (
      <div>
        {
          [...Array(3)].map((_, i) => (
            <div key={i} className="board-row">
              {
                [...Array(3)].map((_, j) => this.renderSquare(3 * i + j))
              }
            </div>
          ))
        }
      </div>
    );
  }

P.S. Je fais aussi les défis dans le nouveau React Tutorial . = p

3
fasfsfgs

Cela devrait résoudre le problème auquel vous faites face.

Cela ajoute une autre boucle, même pour la fonction renderSquare (i) interne . Il fait ce que vous voulez, c'est-à-dire affiche 3 colonnes avec 3 cellules pour le jeu tic tac toe.

 render() {
    let count = 0;
    const index = [1, 2, 3];
    return (
      <div>
        {index.map((v, i) => {
          return (
            <div key={i} className="board-row">
              {index.map((v2, i2) => {
                return this.renderSquare(count++);
              })}
            </div>
          );
        })}
      </div>
    );
  }
0
nitinkaveriappa

Vous poussez des fonctions dans le tableau board. Si vous voulez les rendre, vous devez appeler ces fonctions comme

{board[0]()}

J'ai préparé un exemple qui couvre votre problème: http://jsbin.com/hofohiy/edit?js,output

0
hinok

Je travaille également sur le didacticiel React. Merci pour vos réponses. Je suis arrivé à cette solution:

render() {
    const rows = [];
    for(let i = 0; i<9; i=i+3) {
        const oneRow = [];
        for(let j = i; j < i+3; j++) {
            oneRow.Push(this.renderSquare(j, j))
        }
        rows.Push(<div className="board-row" key={i + 'someId'}>{oneRow}</div>)
    }
    return (
        <div>
            {rows}
        </div>
    );
}

Où j'ai changé renderSquare pour définir une clé pour le composant Square, en tant que second argument. 

renderSquare(i, key) {
    return (
        <Square
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
            key={key}
        />
    );
}
0
Mihai Marinescu

Démo en direct sur codepen

Boucles imbriquées dans render() fonction (explication dans les commentaires :)

class Board extends React.Component {
  renderSquare(i) {
    return (
      <Square
        value={this.props.squares[i]}
        key={i}
        onClick={() => this.props.onClick(i)}
      />
    );
  }

  render() {
     var self = this;
    return (
      <div>
      // you can use: [...Array(3)] instead of [1,2,3]
        {[1, 2, 3].map(function(row, rowIdx) { // create rows 
          return (
            <div className="board-row" key={rowIdx}>
              {
              // you can use: [...Array(3)] instead of [1,2,3]
              [1, 2, 3].map((col, colIdx) => { // create columns
                return self.renderSquare((3 * rowIdx) + colIdx); // calculate square index
              })
              }
            </div>
          );
        })}
      </div>
    );  
  }
}
0
Legends