Reputation: 349
I have the following code:
import React, { useState, useEffect} from 'react';
import Board from './Board';
import Player from '../functions/Player'
function Game() {
const [computer, setComputer] = useState(Player(1,false));
const [computerBoard, setComputerBoard] = useState(new Array(100).fill(-1));
const sendAttack = (location) => {
// Activates everytime I click Board component
let compCopy = computer;
compCopy.receiveAttack(location);
setComputer(compCopy);
setComputerBoard(compCopy.getHitBoard());
console.log(compCopy.getHitBoard()); // always prints, each time I do sendAttack()
// and the hitBoard does change, shows a different hitBoard everytime I click!
}
useEffect(() => {
console.log('something has changed') // print (twice for some reason) only on render, why?
})
useEffect(() => {
console.log('computer hit has changed') // prints only on render and on the first setAttack()
},[computer]);
useEffect(() => {
console.log('computer board has changed') // prints on render
// and once it works but only on first sendAttack()
},[computerBoard])
return (
<div className="game">
<Board hitBoard ={computer.getHitBoard()} sendAttack={sendAttack} />
</div>
);
}
export default Game;
The problem is that I want that the Board
components hitBoard prop
will keep getting updated whenever sendAttack()
has finished updating. But it never does update it except on render (and actually just one time for the first sendAttack()). I don't understand why when I setComputer
it doesn't initiate a useEffect()
Is there an obvious mistake in my code? Thanks for the tips.
Upvotes: 0
Views: 1176
Reputation: 74
The answer given by @Atmas above, is correct. I'd tweak it a bit by having receiveAttack()
return a new object that is a copy of the one passed in with the additional changes. That's a more robust solution to data management in general - don't modify objects, make new ones and return them. Also, that idea of comparing object IDs rather than the content of the object is something you're going to hit all the time in React and various React libraries.
Here's a useful guide that talks about exactly what you're trying to do - use an object as a React state variable:
Also, you don't need a useEffect()
to debug this stuff. Just a regular ol' console log placed right above your return statement will print when the component re-renders.
Upvotes: 2
Reputation: 2393
I don't think your compCopy is actually a new object. If the object isn't different then setComputer likely won't be different therefore the effect won't trigger. Try something like let compCopy = makeANewCopyOf(computer)
such that compCopy is a brand new object that you have cloned yourself.
Upvotes: 2