使用useState时二维网格未重新渲染,如何实现重新渲染?
解决React网格点击不触发重新渲染的问题
问题核心在于你直接修改了state里的对象引用,然后把同一个数组传给setGrid——React靠引用变化判断状态更新,引用没改就不会触发重渲染。
具体修改方案:
- 不要直接修改原state数组,先创建网格的副本,修改副本里的属性后再更新状态
- 二维数组需要逐层复制,避免修改原数组的引用
修改后的handleClick函数:
const handleClick = (rowIndex, colIndex) => { // 创建网格的深副本(逐层复制) const newGrid = initialGrid.map(row => [...row]); // 修改副本中的节点属性 newGrid[rowIndex][colIndex].isGood = true; // 用新副本更新状态 setGrid(newGrid); };
另外,全局变量grid和createNodes的写法可能导致组件初始化时的副作用,建议把网格初始化放到useState的初始化函数里,避免全局变量污染:
// 替换原来的全局grid和createNodes const createNodes = () => { const grid = []; for (let row = 0; row < totalRows; ++row) { const newRow = []; for (let col = 0; col < totalCols; ++col) { newRow.push(new Node(row, col)); } grid.push(newRow); } return grid; }; // 在组件里初始化state const [initialGrid, setGrid] = useState(createNodes());
完整修改后的代码:
import { useState } from "react"; import "./App.css"; class Node { constructor(x, y) { this.row = x; this.col = y; this.isGood = false; } } const totalRows = 5; const totalCols = 5; const createNodes = () => { const grid = []; for (let row = 0; row < totalRows; ++row) { const newRow = []; for (let col = 0; col < totalCols; ++col) { newRow.push(new Node(row, col)); } grid.push(newRow); } return grid; }; const App = () => { const [initialGrid, setGrid] = useState(createNodes()); const handleClick = (rowIndex, colIndex) => { // 创建网格副本 const newGrid = initialGrid.map(row => [...row]); newGrid[rowIndex][colIndex].isGood = true; setGrid(newGrid); }; const getNodeClass = (node) => { return node.isGood ? "node-good" : "node"; }; return ( <div> {initialGrid.map((row, rowIndex) => ( <div key={rowIndex} className="rows"> {row.map((column, columnIndex) => ( <div className={getNodeClass(column)} id={`${rowIndex}-${columnIndex}`} key={columnIndex} onClick={() => handleClick(rowIndex, columnIndex)} ></div> ))} </div> ))} </div> ); }; export default App;
这样修改后,每次点击都会创建新的数组副本,React检测到state引用变化,就会触发重新渲染,单元格的样式也会跟着更新。
内容的提问来源于stack exchange,提问作者Jigyansu Nanda
相关产品推荐
相关产品推荐

