React开发问题:子组件未接收父组件更新后的状态数组
React状态更新后子组件未接收新值问题
我在用React开发一款类似Yahtzee的游戏,遇到父组件更新后的值无法传递给子组件的问题:
- 点击当前回合的骰子时,调用方法将
current数组对应位置设为0,并把该骰子的值同步到keep数组对应位置; - 点击
keep数组中的骰子时,值反向传递到current数组,最终每个骰子应显示对应数组项的当前值。
点击任意数组中的骰子后,通过console.log验证,current和keep数组的状态已正确更新,但更新后的数组似乎未传递给子组件(同样通过console.log验证)。
相关代码
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); // 输出看似正确 console.log("Keep: " + keepValues); // 输出看似正确 } }; 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); // 输出看似正确 console.log("Keep: " + keepValues); // 输出看似正确 } }; return ( <div> <Current values={currentValues} onDiceClicked={moveCurrentToKeep} /> <Keep values={keepValues} onDiceClicked={moveKeepToCurrent} /> </div> ); }
Current.js
const Current = ({ values, onDiceClicked }) => { console.log("Current: " + values); // 无输出!!! 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); // 无输出!!! 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> ); };
问题原因与修复方案
核心问题
你直接修改了React状态数组的引用:
let curr = currentValues; // 只是复制了数组的引用,不是新数组 let keep = keepValues;
React通过浅比较判断状态是否变化,当你修改原数组并把同一个引用传给setCurrentValues/setKeepValues时,React会认为状态没有改变,不会触发组件重新渲染,子组件自然接收不到新值。
另外,你看到的console.log输出看似正确,是因为你直接篡改了原数组的内容,虽然状态没更新,但原数组已经被修改,这违背了React状态不可变的原则。
修复代码
修改moveCurrentToKeep和moveKeepToCurrent方法,创建数组的新副本再修改:
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) { // 创建数组副本,避免修改原状态引用 const curr = [...currentValues]; const keep = [...keepValues]; const valueToSwitch = curr[index]; curr[index] = 0; keep[index] = valueToSwitch; setCurrentValues(curr); setKeepValues(keep); } }; const moveKeepToCurrent = (index) => { if (keepValues[index] > 0) { const curr = [...currentValues]; const keep = [...keepValues]; const valueToSwitch = keep[index]; keep[index] = 0; curr[index] = valueToSwitch; setCurrentValues(curr); setKeepValues(keep); } }; return ( <div> <Current values={currentValues} onDiceClicked={moveCurrentToKeep} /> <Keep values={keepValues} onDiceClicked={moveKeepToCurrent} /> </div> ); }
额外说明
- 用扩展运算符
[...arr]是创建一维数组浅副本的简单方式,也可以用arr.slice()或Array.from(arr); - 如果是嵌套对象/数组,需要使用深拷贝,但这里是一维数组,浅拷贝足够;
- 始终遵守React状态不可变原则,避免直接修改状态值。
内容的提问来源于stack exchange,提问作者vtomic85
相关产品推荐
相关产品推荐

