I'm making a tic-tac-toe game with react, and I passed the parent setState function, to change the board, to the child component.
After that, I put a useEffect in the Parent Component ( useEffect(()=> ... , [board])
) to do an action whenever this state changes. But it doesn't do anything when I use the setState inside the child. The console.log below is displaying true, and that is probably the reason the useEffect is no updating.
function handleClick(_, i:number) {
setBoard(prevBoard => {
const newBoard = board
newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
console.log(newBoard == prevBoard)
return newBoard
})
...
}
CodePudding user response:
The console.log below is displaying true, and that is probably the reason the useEffect is no updating.
That's exactly it. State in react is intended to be immutable. When you call setBoard
, react will compare the old state with the new state using an Object.is check (which is similar to ===
). If they're the same, then it looks like nothing changed, and so react skips the rerender. React will not check the properties inside your state to see if they changed, since that could be expensive.
Instead, make sure you create a new state instead of modifying the old one:
setBoard(prevBoard => {
const newBoard = [...board]; // <--- creating a shallow copy
newBoard[i] = dictIconToValue[icon] as typeof prevBoard[0]
return newBoard
})
CodePudding user response:
As far as React is concerned, the state isn't actually being updated because it's still the same object reference. You're mutating state instead of creating a new instance.
This doesn't copy the array, it just points a new variable to the same reference:
const newBoard = board
So any changes made to newBoard
are being made directly on the state instance (mutating it). Instead, create a new array with copies of the existing array's elements (which may themselves be references, but that's often an edge case and shouldn't be a problem here):
const newBoard = [...board]
In this case newBoard
is a new object reference entirely, so when it gets set to the state then React will see it as updated state.