React组件传递数字类型key属性为何返回undefined?
React网格组件状态更新时key为undefined的问题
问题场景
我想要创建一个组件网格,并保存每个组件的状态。初始化了对应网格组件的对象数组cellsGrid,代码如下:
let count = 0; for(let i = 0; i < 15; i++){ for(let j = 0; j < 30; j++){ count++; let x = 0; if(i % 2 !== 0){ x = j * WIDTH_OF_CELL + OFFSET_X; } else { x = j * WIDTH_OF_CELL + OFFSET_X + 24; } const y = i * HEIGHT_OF_CELL + OFFSET_Y; let cell = { y: y, x: x, centerX: x + 25, centerY: y + 25, state: 0, key: count } cellsGrid.push(cell); } }
中间组件接收cellsGrid作为prop,映射为Cell组件:
return ( <div> {cellsGrid.map((item) => <Cell key={item.key} postitX={item.x} postitY={item.y} edit={edit} state={item.state} handleClick={handleClick}> </Cell> )} </div> )
点击单元格时要把state从0更新为1,因此传递了handleClick函数:
const handleClick = (event, state, key, callback) => { callback(); let index = cellsGrid.findIndex(cell => cell.key === key); cellsGrid[index].state = state; };
Cell组件内部调用该函数:
onClick={event => handleClick(event, currentState.state, key, nextState)}
但点击时抛出错误:
Uncaught TypeError: Cannot set properties of undefined (setting 'state')
打印key和index得到:
输出结果:
undefined-1
问题原因
- React的
key属性不传递给组件props:父组件中给Cell设置的key={item.key}是React用于列表渲染的内部标识,不会被传递到Cell组件内部,因此Cell里的key变量是undefined。 - 直接修改数组不触发React更新:即便找到正确索引,直接修改
cellsGrid[index].state也不会触发组件重新渲染,因为React依赖状态更新机制感知变化。
解决方案
1. 给Cell组件传递cellKey prop
在父组件映射Cell时,额外传递包含key值的prop(比如cellKey):
return ( <div> {cellsGrid.map((item) => <Cell key={item.key} cellKey={item.key} {/* 新增:把key作为组件props传递 */} postitX={item.x} postitY={item.y} edit={edit} state={item.state} handleClick={handleClick}> </Cell> )} </div> )
2. 在Cell组件中使用cellKey
确保Cell组件接收cellKey prop,并在点击时传递给handleClick:
// 以函数组件为例,先解构接收cellKey const Cell = ({ cellKey, state, handleClick, ...rest }) => { // 假设currentState和nextState是组件内部状态 return ( <div onClick={event => handleClick(event, currentState.state, cellKey, nextState)}> {/* 组件内容 */} </div> ) }
3. 正确更新React状态
不要直接修改原数组,使用状态更新函数创建新数组(假设cellsGrid是用useState管理的状态):
// 初始化状态 const [cellsGrid, setCellsGrid] = useState(initialCellsGrid); const handleClick = (event, newState, key, callback) => { callback(); // 生成新数组更新状态,触发重新渲染 setCellsGrid(prevGrid => prevGrid.map(cell => cell.key === key ? { ...cell, state: newState } : cell ) ); };
修改后,点击单元格就能正确找到对应元素,更新其状态并触发组件重新渲染。
内容的提问来源于stack exchange,提问作者Peartree
相关产品推荐
相关产品推荐

