React状态变更后组件未重新渲染,点击按钮无法修改网格大小
React网格尺寸不更新的问题原因与解决方案
问题根源
你在Picross组件中用useState(temp_g)初始化网格状态,但React的useState有个关键特性:初始值仅在组件第一次渲染时被赋值。当父组件的size变化,传递给Picross的rows/cols props更新时,组件会重新渲染,temp_g也会重新计算,但useState不会自动用新的temp_g覆盖已有的grid状态——这就是网格尺寸没跟着变的原因。
两种正确实现方式
方式1:移除组件内的useState(你已验证有效)
如果网格不需要后续修改(比如用户点击编辑单元格),完全没必要把temp_g存在组件状态里,直接用计算后的数组渲染即可。这样每次props变化时,temp_g都会重新生成,网格自然会更新:
function Picross({ rows, cols }) { let temp_g = new Array(rows); for (let i = 0; i < rows; i++) { temp_g[i] = new Array(cols); for (let j = 0; j < cols; j++) { temp_g[i][j] = i + j; } } return ( <div className="grid col s9"> {temp_g.map((row, rowIdx) => ( <div className="blockrows" key={rowIdx}> {row.map((val, colIdx) => ( <Node num={val} key={`${rowIdx}-${colIdx}`} /> ))} </div> ))} </div> ); }
方式2:用useEffect监听props更新状态(需修改网格时用)
如果后续需要让用户修改网格内容,必须把grid存在状态里,这时候要加useEffect监听rows和cols的变化,当尺寸改变时重新生成网格并更新状态:
import { useState, useEffect } from 'react'; function Picross({ rows, cols }) { const [grid, updateGrid] = useState([]); // 当rows或cols变化时,重新生成网格 useEffect(() => { const newGrid = new Array(rows); for (let i = 0; i < rows; i++) { newGrid[i] = new Array(cols); for (let j = 0; j < cols; j++) { newGrid[i][j] = i + j; } } updateGrid(newGrid); }, [rows, cols]); return ( <div className="grid col s9"> {grid.map((row, rowIdx) => ( <div className="blockrows" key={rowIdx}> {row.map((val, colIdx) => ( <Node num={val} key={`${rowIdx}-${colIdx}`} /> ))} </div> ))} </div> ); }
额外提醒
渲染列表时一定要给每个元素加唯一的key属性,这能让React更高效地更新DOM,避免控制台警告和不必要的性能损耗。
内容的提问来源于stack exchange,提问作者Tablesalt
相关产品推荐
相关产品推荐

