React动态生成二维状态数组 单元素修改触发子数组同步更新问题
问题原因
你动态初始化board时的写法存在JavaScript引用类型的经典误用:
Array(lives).fill(Array(correctWord.length).fill(""))中,传入fill()的内层数组是同一个引用类型实例,外层数组的所有位置存储的都是指向这同一个内层数组的内存地址,没有为每一行生成独立的数组。- 你在输入逻辑中写的
const newBoard = [...board]仅对外层数组做了浅拷贝,没有拷贝内层的行数组,所有行仍然指向同一个共享数组。因此修改任意一行的指定位置时,本质是修改所有行共同引用的那一个数组,自然会出现所有行对应位置同步填充字符的现象。
静态写法正常运行的原因
静态初始化的代码[["","","","",""],["","","","",""]]是通过数组字面量创建的,方括号内的两个内层数组是完全独立的两个实例,分别占用不同内存空间,互相没有引用关联,因此修改其中一行不会影响其他行。
修复方案
1. 修正状态初始化逻辑
不要用fill()直接填充引用类型值,改用Array.from为每一行生成独立的数组实例:
const correctWord = "RIGHT"; const [lives, setLives] = useState(2); const [board, setBoard] = useState( Array.from({ length: lives }, () => Array(correctWord.length).fill("")) );
2. (推荐)使用完全不可变的状态更新逻辑
为了彻底避免浅拷贝带来的状态突变问题,更新board时建议基于前序状态做全量拷贝更新,同时可以顺手修复你原有代码中未从事件对象正确取key值的小问题:
const selectKey = (event) => { const key = event.target.value; // 按实际业务的事件取值逻辑调整即可 if (current.letterPos >= correctWord.length) return; setBoard(prevBoard => { return prevBoard.map((row, rowIndex) => { // 非当前行直接拷贝返回 if (rowIndex !== current.attempt) return [...row]; // 当前行仅替换对应位置的字符 return row.map((cell, colIndex) => { return colIndex === current.letterPos ? key : cell; }); }); }); setCurrent(prev => ({ ...prev, letterPos: prev.letterPos + 1 })); };
内容的提问来源于stack exchange,提问作者ABpositive
相关产品推荐
相关产品推荐

