Mohamed Oun Mohamed Oun - 23 days ago 5
Javascript Question

Pass state to child component - React Tutorial

I've been following the official React Tutorial here. And I've reached the point where when I click a square, it calls the Board's handleClick function to update the squares states.
However, after the states are updated in the Board class, they aren't propagated down to the squares' states.

Here's my code:

class Square extends React.Component {
constructor() {
super();
this.state = {
value: null,
};
}
render() {
return (
<button className="square" onClick={() =>this.props.onClick()} >
{this.state.value}
</button>
);
}
}

class Board extends React.Component {
constructor() {
super();
this.state = {
squares: Array(9).fill(null),
};
}

renderSquare(i) {
return <Square value={this.state.squares[i]} onClick={() => this.handleClick(i)} />;
}
render() {
const status = 'Next player: X';
return (
<div>
<div className="status">{status}</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>
);
}
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = 'X';
debugger;
this.setState({squares: squares});
}
}


https://codepen.io/mohamed3on/pen/jVVyWZ?editors=1010
I've followed the tutorial exactly until the "Why Immutability Is Important" part. I know

Answer

You are already passing each square's value as a property, but you are trying to pick it up from state in Square.render(). You should be using {this.props.value}, and lose the state initialization in the constructor, you don't need it. The general pattern is: the container component manages state; then the contained components should be stateless. As a general guideline, it is also advisable to avoid using state all along.