Wednesday, June 5, 2024
 Popular · Latest · Hot · Upcoming
143
rated 0 times [  146] [ 3]  / answers: 1 / hits: 44174  / 8 Years ago, sun, january 15, 2017, 12:00:00

I have a little issue with React. I can't create a nested component with a for loop. What I want to do is create 9 cells of a table and then create 3 rows with 3 cells for every row and after that mount the 3 rows together and create a board 9x9.



Let say that I want to get something like this, but using a loop



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


}



I searched others question for hours and I think my code is almost correct but it does not render what I want. I only get a white page.



here is my 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>
);
}


I always get on the screen something like this:



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


I want to clarify that I am sure that the rest of the code with which that component (Board) interacts has no issues.



I am new in react and if someoane can help me i will apreciate very much.
Sorry for my poor English



EDIT1:
following marklew examples i should be able to do something like this



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

}


but it doesn't do what I want. I obtain just a column with 9 cells and the cells are the same objects. I dont understand why. (I understand that are the same objects because i assign a handle function onClick when I create them like that:



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


and I get the X drown in 3 cells simultaneously



EDIT2:
I reached a 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>
);

}


}



but is not what I want. I want another loop even for the intern renderSquare(i) function.


More From » loops

 Answers
13

To render a list of elements inside JSX, you can do something like that:



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

}
</div>;
}


Just wrap your array of components into {} in your JSX.



To clarify a bit, this is the same logic of:



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


Note that everytime you render an array of components, you must provide a key prop, as pointed here.



Also, if you want simply print row value in your render function, you should replace:



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


with:



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


or, yet, replacing forEach and push with map:



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


EDIT I created a fiddle with a 9x9 board using your code as a base: https://jsfiddle.net/mrlew/cLbyyL27/ (you can click on the cell to select it)


[#59348] Thursday, January 12, 2017, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
bradford

Total Points: 709
Total Questions: 117
Total Answers: 91

Location: Sao Tome and Principe
Member since Wed, Dec 21, 2022
1 Year ago
;