web-dev-qa-db-ja.com

React-ループを持つネストされたコンポーネントを作成する

Reactには少し問題があります。 forループでネストされたコンポーネントを作成できません。私がやりたいのは、テーブルの9つのセルを作成し、すべての行に3つのセルを持つ3つの行を作成し、その後、3つの行を一緒にマウントして9x9のボードを作成することです。

このようなものを取得したいが、ループを使用すると言いましょう

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>
    );        
}

}

私は他の人の質問を何時間も検索しました。私のコードはほぼ正しいと思いますが、私が望むものをレンダリングしません。ホワイトページしか表示されません。

ここに私のコードがあります:

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>
    );        
}

私はいつも次のようなものを画面に表示します:

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

そのコンポーネント(ボード)が対話するコードの残りの部分には問題がないと確信していることを明確にしたいと思います。

私は反応するのが初めてであり、someoaneが私を助けることができれば私は非常にapreciateします。下手な英語でごめんなさい

EDIT1:次のmarklewの例私はこのようなことをすることができるはずです

    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>
    );

}

しかし、それは私が望むことをしません。 9個のセルを持つ列を取得しますが、セルは同じオブジェクトです。理由がわかりません。 (私はそのようなオブジェクトを作成するときにonClickのハンドル関数を割り当てるため、同じオブジェクトであることを理解しています:

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

xを3つのセルに同時にdrれさせます

EDIT2:私は解決策に到達しました:

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>
    );

}

}

しかし、私が望むものではありません。 intern renderSquare(i)関数に対しても別のループが必要です。

10
neboduus

JSX内の要素のリストをレンダリングするには、次のようなことができます。

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

        }
    </div>;
}   

コンポーネントの配列をJSXで{}にラップするだけです。

少し明確にするために、これは同じロジックです:

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

コンポーネントの配列をレンダリングするたびに、 here のように、key propを提供する必要があることに注意してください。

また、レンダリング関数で単純に行の値を出力する場合は、次のものを置き換える必要があります。

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

で:

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

または、まだforEachPushmapに置き換えます:

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

[〜#〜] edit [〜#〜]コードをベースとして9x9ボードでフィドルを作成しました: https: //jsfiddle.net/mrlew/cLbyyL27/ (セルをクリックして選択できます)

12
mrlew

あなたもJS Reactチュートリアルをやっています!私がやったことはここにありますが、これらの個々のキーのそれぞれを与える良い方法がなければならないので私はこれに取り組んでいます。

Xが3つの正方形に描かれた場所であなたが走っていたのと同じ問題に出くわしました。これは、正方形をレンダリングするときに「i」の一部が複製されたためです。したがって、たとえば「i」が2の正方形が複数ありました(少なくとも私の問題ではそうでした)。

各スクエアにはインデックスがありますか? [0,1,2,3,4,5,6,7,8]。

まず、これらを行にレンダリングできるように、これらがどのように関連しているかを見つける必要があります!したがって、あなたの例では、index1とindex2があります。これらは、ボードの正方形のx座標とy座標を指すと思います。上記の配列を書き換えると、[{0,0}、{1,0}、{2,0}、{0,1}、{1,1}、{2,1}、{0、 2}、{1,2}、{2,2}] {x、y}形式を使用します。これらの値([0,1,2,3,4,5,6,7,8]で開始した元の値の配列を取得するためにindex1とindex2から取得する値)をどのように使用できますか?

私がやったのは、3 * x + y(またはループで、3 * i + j)でした。このように、各正方形には固有の「i」値が関連付けられています。

ループを設定した後、 this SO postを使用して、別の関数から作成した要素を正しく返します(コードをよりクリーンに保つための貧弱な試み))。

これが私がやったことですが、キーを正しく設定することを確認する必要があります。これが実際にこの投稿に出くわした方法です。

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;
}

次に、Boardでのレンダリング関数は次のようになります。

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

ここと Loop inside 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>
    );
  }

追伸また、新しい React Tutorial でチャレンジを行っています。 = p

3
fasfsfgs

Reactチュートリアルの例を見ていると仮定します。指示が明示的に指摘しているように、アイデアは1つだけではなく2つのループを作成することです。

この例の最初のループは3行を作成します。 2番目のネストされたループは、必要な3つの列を作成し、renderSquare関数を介して各位置のSquareを返します。両方のループのインデックスを使用して、対応するインデックスを正方形に正しく割り当てることに気付くかもしれません。

return (
    <div>
      {[0,1,2].map(i => {
        return (
          <div className="board-row">
            {[0,1,2].map(j => {
              return this.renderSquare(3*i + j)
            })}
          </div>
        );
      })}
    </div>
  );
1
Mateo Marin

codepenのライブデモ

render() functionのネストされたループ(コメントの説明:)

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>
    );  
  }
}
1
Legends

これにより、直面している問題が解決するはずです。

これにより、intern renderSquare(i)関数に対しても別のループが追加されます。それはあなたが望むことをします、すなわち三目並べゲームのために3つのセルを持つ3つの列を表示します。

 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

関数をboard配列にプッシュしています。それらをレンダリングしたい場合は、次のような関数を呼び出す必要があります

{board[0]()}

あなたの問題をカバーする例を用意しました: http://jsbin.com/hofohiy/edit?js,output

0
hinok

最初の解決策:

import React from 'react';
import Square from './Square';

export default
class Board extends React.Component {
  render() {
    const board2 = [];

    for (let i = 0; i < 3; i++) {
      const s = [];
      for (let k = 0; k < 3; k++) {
        s[k] = <Square
          key     ={3*i+k}
          value   ={this.props.squares[3*i+k]}
          onClick ={()=>this.props.onClick(3*i+k)}
          />;
      }
      board2[i] = <div className="board-row" key={i}>{s}</div>;
    }
    ///////////////////////////////////////
    return (
      <div>{board2}</div>
    );
  }
}

2番目のソリューション:

import React from 'react';
import Square from './Square';

export default
class Board extends React.Component {
  render() {    
    let board   =Array(3).fill(null);
    let square  =Array(3).fill(null);

    const x = board.map((b,bIndex)=>{
      return<div className="board-row" key={bIndex}>
        {
          square.map((s, sIndex)=>{
            return <Square
            key     ={3*bIndex+sIndex}
            value   ={this.props.squares[3*bIndex+sIndex]}
            onClick ={()=>this.props.onClick(3*bIndex+sIndex)}
            />;
          })
        }
      </div>;
    });
    ///////////////////////////////////////
    return (
      <div>{x}</div>
    );
  }
}

平方:

import React from 'react';

export default
function Square(props) {
  console.log('square render')
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}
0
Fatih Ertuğral

私はReactチュートリアルにも取り組んでいます。ご回答ありがとうございます。このソリューションに到達しました。

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>
    );
}

2番目の引数として、Squareコンポーネントのキーを設定するためにrenderSquareを変更しました。

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