Get Started with Modern React: Learn by Doing
S03・V12: Setting State
- We will show you how to set values in our `squares` state array.
Setting State
As a next step, when we click on a square, we want to show an X
. This entails updating our state variable squares
in the Board
component, so that the element representing the Square
clicked, changes its value from null
to X
.
In React, we should not mutate state directly, for reasons we will explain in more detail in the next video. We will first make a copy of the squares
array, then make changes to the copy, and finally switch out the current state with the modified state.
Let’s add comments in our handleClickEvent
function breaking down this process.
const handleClickEvent = i => {
// Make a copy of `squares` array
// Mutate the copy, setting the i-th element to `'X'`
// Set the `squares` state to be the mutated copy
};
Let’s make a copy of the squares
array using “array spread syntax”, and assign the copy to a variable we will call newSquares
.
const handleClickEvent = i => {
// Make a copy of `squares` array
const newSquares = [...squares]; // Mutate the copy, setting the i-th element to `'X'`
// Set the `squares` state to be the mutated copy
};
As a second step, let’s update the copy, setting the clicked element to 'X'
.
const handleClickEvent = i => {
// Make a copy of `squares` array
const newSquares = [...squares];
// Mutate the copy, setting the i-th element to `'X'`
newSquares[i] = 'X'; // Set the `squares` state to be the mutated copy
};
Finally, let’s use our state setter called setSquares
, defined in our useState
hook, to set the state to be the modified copy.
const handleClickEvent = i => {
// Make a copy of `squares` array
const newSquares = [...squares];
// Mutate the copy, setting the i-th element to `'X'`
newSquares[i] = 'X';
// Set the `squares` state to be the mutated copy
setSquares(newSquares); };
Now test this out in the browser. We will first click on the square with index 2
. Now we will click on the square with index 7
. Our UI is updating as expected, showing an 'X'
when we click on a square.
We have successfully set the squares
state array on the Board
. Before we move on to the next video, let’s do some minor refactoring. Our initialSquares
array can be simplified.
const initialSquares = [
null, null, null,
null, null, null,
null, null, null,
];
const initialSquares = Array(9).fill(null);
This is a shorter way of creating an array of 9 elements and making them all null
. Now, we can delete the longer definition of initialSquares
. Next, we will remove the comments.
Finally, we will update the value passed to onClick
in the Square
component’s button
, removing the superfluous arrow function. We can do this because () => props.onClickEvent()
is equivalent to props.onClickEvent
.
const Square = props => {
return (
<button
className="square"
onClick={props.onClickEvent} >
{props.value}
</button>
);
};
Code Snapshot
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const Square = props => {
return (
<button
className="square"
onClick={props.onClickEvent}
>
{props.value}
</button>
);
};
const Board = () => {
const initialSquares = Array(9).fill(null);
const [squares, setSquares] = useState(initialSquares);
const handleClickEvent = i => {
const newSquares = [...squares];
newSquares[i] = 'X';
setSquares(newSquares);
};
const renderSquare = i => {
return (
<Square
value={squares[i]}
onClickEvent={() => handleClickEvent(i)}
/>
);
};
return (
<div style={{
backgroundColor: 'skyblue',
margin: 40,
padding: 20,
}}>
Board
<div className="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
</div>
);
};
const Game = () => {
return (
<div className="game">
Game
<Board />
</div>
);
};
ReactDOM.render(
<Game />,
document.getElementById('root')
);
Summary
We showed the 3-step process to correctly update a state array. We first copied the array, then we mutated the copy, and finally we set the state array to be the mutated copy.
Next Up…
In the next video, we will explain why this 3-step process for updating non-scalar state is necessary in React.