I'm making a Yahtzee-like game in React and I have a problem with updated values not being passed from a parent to a child.
When a player clicks a dice from the current attempt, I'm calling a method which will set that value in the "current" array to 0 and update the corresponding value in the "keep" array to the value of that dice. The same thing happens when a dice in the "keep" array is clicked - the value should be transferred to the "current" array. Finally, every dice should display the current value of the corresponding array item.
When I click a dice in any array, the states of both arrays ("current" and "keep") are updated properly (I verified that using console.log), but it looks like the updated arrays are not being passed to the child components (also verified through console.log).
What could be the problem?
Game.js
const Game = () => {
const [currentValues, setCurrentValues] = useState([0, 0, 0, 0, 0, 0]);
const [keepValues, setKeepValues] = useState([0, 0, 0, 0, 0, 0]);
const moveCurrentToKeep = (index) => {
if (currentValues[index] > 0) {
let curr = currentValues;
let keep = keepValues;
let valueToSwitch = curr[index];
curr[index] = 0;
keep[index] = valueToSwitch;
setCurrentValues(curr);
setKeepValues(keep);
console.log("Curr: " currentValues); // The output is correct
console.log("Keep: " keepValues); // The output is correct
}
};
const moveKeepToCurrent = (index) => {
if (keepValues[index] > 0) {
let curr = currentValues;
let keep = keepValues;
let valueToSwitch = keep[index];
keep[index] = 0;
curr[index] = valueToSwitch;
setCurrentValues(curr);
setKeepValues(keep);
console.log("Curr: " currentValues); // The output is correct
console.log("Keep: " keepValues); // The output is correct
}
};
return (
<div>
<Current values={currentValues} onDiceClicked={moveCurrentToKeep} />
<Keep values={keepValues} onDiceClicked={moveKeepToCurrent} />
</div>
);
}
Current.js
const Current = ({ values, onDiceClicked }) => {
console.log("Current: " values); // This doesn't output anything!!!
return (
<div>
<DiceField value={values[0]} onClick={() => onDiceClicked(0)} />
<DiceField value={values[1]} onClick={() => onDiceClicked(1)} />
<DiceField value={values[2]} onClick={() => onDiceClicked(2)} />
<DiceField value={values[3]} onClick={() => onDiceClicked(3)} />
<DiceField value={values[4]} onClick={() => onDiceClicked(4)} />
<DiceField value={values[5]} onClick={() => onDiceClicked(5)} />
</div>
);
};
Keep.js
const Keep = ({ values, onDiceClicked }) => {
console.log("Keep: " values); // This doesn't output anything!!!
return (
<div>
<DiceField value={values[0]} onClick={() => onDiceClicked(0)} />
<DiceField value={values[1]} onClick={() => onDiceClicked(1)} />
<DiceField value={values[2]} onClick={() => onDiceClicked(2)} />
<DiceField value={values[3]} onClick={() => onDiceClicked(3)} />
<DiceField value={values[4]} onClick={() => onDiceClicked(4)} />
<DiceField value={values[5]} onClick={() => onDiceClicked(5)} />
</div>
);
};
DiceField.js
const DiceField = ({ value, onClick }) => {
return (
<button onClick={onClick}>
{value !== 0 ? value : ""}
</button>
);
};
CodePudding user response:
You would need to clone the array before updating for React to know that you have updated the value.
React performs and Object.is
check which checks the reference of the object and since you are mutating the array in place, the reference remains the same and hence it infers that nothing has changed and doesn't re-render
const moveCurrentToKeep = (index) => {
if (currentValues[index] > 0) {
let curr = [...currentValues]; // clone the array here
let keep = [...keepValues] ; // clone the array here
let valueToSwitch = curr[index];
curr[index] = 0;
keep[index] = valueToSwitch;
setCurrentValues(curr);
setKeepValues(keep);
console.log("Curr: " currentValues); // The output is correct
console.log("Keep: " keepValues); // The output is correct
}
};
const moveKeepToCurrent = (index) => {
if (keepValues[index] > 0) {
let curr = [...currentValues];
let keep = [...keepValues];
let valueToSwitch = keep[index];
keep[index] = 0;
curr[index] = valueToSwitch;
setCurrentValues(curr);
setKeepValues(keep);
console.log("Curr: " currentValues); // The output is correct
console.log("Keep: " keepValues); // The output is correct
}
};