You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中修改div的className后界面未更新的问题

问题分析与解决

问题现象

尝试通过每秒修改数组状态切换div的className来改变背景色,console.log(grid[0][0])显示数据已修改,但首次迭代后div外观不再更新。index.js中传入props:<App row={5} col={10}/>。

代码示例

App.js

import React, { useState, useEffect } from 'react';
import './App.css';

function App(props) {
  // Initializing the grid.
  let grid = initializeGrid(props.row, props.col);

  const [gridData, setGridData] = useState(grid);

  useEffect(() => {
    const interval = setInterval(() => {
      setGridData(gridData => updateGrid(gridData));
    }, 2000);
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="container">
      {gridData.reduce(function (acc, itm, idx) {
        let item = itm.map((cell, index) => <div key={acc.length + index} className={cell.state ? "state-on" : "state-off"}>{acc.length + index}</div>);
        return acc.concat(item);
      }, [])}
    </div>
  );
}

function initializeGrid(row, col) {
  let cell = { state: false, count: 0 }
  let grid = [];
  for (let y = 0; y < row; y++) {
    grid.push([]);
    for (let x = 0; x < col; x++) {
      grid[y].push(cell);
    }
  }
  return grid;
}

function updateGrid(grid) {
  let currentState = grid[0][0].state;
  currentState ? (grid[0][0] = { state: false, count: 0 }) : (grid[0][0] = { state: true, count: 0 });
  console.log(grid[0][0]);
  return grid;
}

export default App;

App.css

html, body, #root {
  box-sizing: border-box;
  background-color: #ffeead;
  height: 100%;
  padding: 10px;
  margin: 0px;
}

.container {
  height: 100%;
  display: grid;
  grid-gap: 3px;
  grid-template-columns: repeat(10, 80px);
  grid-template-rows: repeat(5, 80px);
  justify-content: center;
  align-content: center;
}

.container>div {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2em;
  color: #ffeead;
}

.state-off {
  background-color: #96ceb4;
}

.state-on {
  background-color: #ff6f69;
}

问题根源

  1. 状态更新未改变引用:React的useState依赖浅比较判断状态是否变化。updateGrid直接修改原数组元素后返回原数组,数组引用未变,React认为状态无更新,因此首次渲染后不再触发重绘。
  2. 初始化单元格引用重复:initializeGrid中所有单元格复用同一个cell对象,导致所有单元格共享同一状态,会引发后续潜在问题。

修复方案

1. 修复updateGrid,创建新数组与对象

修改updateGrid,通过拷贝数组和对象的方式确保返回新引用,让React检测到状态变化:

function updateGrid(grid) {
  // 拷贝二维数组的每一行,避免直接修改原数组
  const newGrid = grid.map(row => [...row]);
  const currentState = newGrid[0][0].state;
  // 创建新的单元格对象替换目标位置
  newGrid[0][0] = { state: !currentState, count: 0 };
  console.log(newGrid[0][0]);
  return newGrid;
}

2. 修复initializeGrid,每个单元格创建独立对象

修改初始化函数,确保每个单元格都是独立对象,避免引用共享:

function initializeGrid(row, col) {
  let grid = [];
  for (let y = 0; y < row; y++) {
    grid.push([]);
    for (let x = 0; x < col; x++) {
      // 每次循环创建新的cell对象
      grid[y].push({ state: false, count: 0 });
    }
  }
  return grid;
}

完整修复后的App.js

import React, { useState, useEffect } from 'react';
import './App.css';

function App(props) {
  // 用函数式初始化避免组件重渲染时重复执行initializeGrid
  const [gridData, setGridData] = useState(() => initializeGrid(props.row, props.col));

  useEffect(() => {
    const interval = setInterval(() => {
      setGridData(gridData => updateGrid(gridData));
    }, 2000);
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="container">
      {gridData.reduce(function (acc, itm, idx) {
        let item = itm.map((cell, index) => <div key={acc.length + index} className={cell.state ? "state-on" : "state-off"}>{acc.length + index}</div>);
        return acc.concat(item);
      }, [])}
    </div>
  );
}

function initializeGrid(row, col) {
  let grid = [];
  for (let y = 0; y < row; y++) {
    grid.push([]);
    for (let x = 0; x < col; x++) {
      grid[y].push({ state: false, count: 0 });
    }
  }
  return grid;
}

function updateGrid(grid) {
  const newGrid = grid.map(row => [...row]);
  const currentState = newGrid[0][0].state;
  newGrid[0][0] = { state: !currentState, count: 0 };
  console.log(newGrid[0][0]);
  return newGrid;
}

export default App;

说明

  • 状态更新时必须返回新的数组/对象引用,React才能识别到状态变化并触发重渲染。
  • 初始化数组时避免复用对象引用,确保每个元素都是独立实例,防止意外的状态同步。

内容的提问来源于stack exchange,提问作者Akbar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:06:20