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

使用React Hook的setState更新二维数组致应用崩溃

React最短路径可视化网格点击崩溃问题修复

问题根源分析

你的代码导致应用崩溃主要有三个核心问题:

  1. 事件处理函数直接执行:渲染网格时onClick={handleMouseDown(rowIndex, columnIndex)}会立即调用函数,而非点击时触发,引发无限状态更新循环。
  2. 二维数组遍历错误:handleMouseDown中用grid.map((node) =>遍历的是整行而非单个节点,无法正确定位目标单元格。
  3. 违反状态不可变性:直接修改原节点对象属性,React无法检测到状态变化,还会导致状态不一致。

修正后的完整代码

import './App.css';
import { useState } from "react";

const start_row = 9;
const start_col = 9;
const end_row = 20;
const end_col = 50;

function App() {
  const [darkMode, setDarkMode] = useState(true);

  function createNode(row, col) {
    return {
      row,
      col,
      isStart: row === start_row && col === start_col,
      isFinish: row === end_row && col === end_col,
      isWall: false, // 重命名为更语义化的isWall
    };
  }

  const createGrid = (rows, cols) => {
    const grid = [];
    for (let row = 0; row < rows; row++) {
      const currentRow = [];
      for (let col = 0; col < cols; col++) {
        currentRow.push(createNode(row, col));
      }
      grid.push(currentRow);
    }
    return grid;
  }

  // 用初始化函数避免每次渲染重复创建初始网格
  const [grid, setGrid] = useState(() => createGrid(30, 65));

  const handleClick = () => {
    setDarkMode(!darkMode);
  }

  const setMode = (style) => {
    let backgroundColor, textColor, buttonColor;

    if (darkMode) {
      backgroundColor = "black";
      textColor = 'white';
      buttonColor = "#303030";
    } else {
      backgroundColor = 'white';
      textColor = 'black';
      buttonColor = "#ffe291";
    }

    if (style === 1) return backgroundColor;
    if (style === 2) return textColor;
    return buttonColor;
  }

  const drawNode = (node) => {
    if (node.isStart) {
      return <img src="https://img.icons8.com/ios-glyphs/30/null/play--v1.png" alt="起点"/>;
    }
    if (node.isFinish) {
      return <img src="https://img.icons8.com/ios-glyphs/30/null/finish-flag.png" alt="终点"/>
    }
    if (node.isWall) {
      return <div className="Wall"></div>
    }
  }

  const nodeName = (row, col) => {
    return `node ${row}-${col}`;
  }

  const handleMouseDown = (targetRow, targetCol) => {
    // 正确遍历二维数组,严格遵循状态不可变性
    const newGrid = grid.map((row, rowIndex) => {
      if (rowIndex !== targetRow) return [...row]; // 非目标行直接复制
      return row.map((node, colIndex) => {
        if (colIndex !== targetCol) return {...node}; // 非目标节点直接复制
        // 创建新节点对象切换墙体状态
        return { ...node, isWall: !node.isWall };
      });
    });
    setGrid(newGrid);
  }

  return (
    <div className="App" style={{ backgroundColor: setMode(1), color: setMode(2) }}>
      <div className="header-container">
        <div className="darkmode-container">
          <label className="darkmode-button" style={{ backgroundColor: setMode(3) }}>
            <input type="checkbox" className="darkmode-input" onClick={handleClick} />
            <span className="darkmode-toggle">
              <img className="moon" src="https://img.icons8.com/sf-regular/48/null/moon-symbol.png" alt="月亮"/>
            </span>
            <img className="sun" src="https://img.icons8.com/material-outlined/24/000000/smiling-sun.png" alt="太阳"/>
          </label>
        </div>
        <div className="header">
          <header>Visualizer</header>
        </div>
      </div>
      <div className="map-container">
        <div className="map">
          {grid.map((row, rowIndex) => (
            row.map((node, colIndex) => (
              <div 
                className={nodeName(rowIndex, colIndex)} 
                onClick={() => handleMouseDown(rowIndex, colIndex)} 
                key={`${rowIndex}-${colIndex}`} // 添加key避免React警告
              >
                {drawNode(node)}
              </div>
            ))
          ))}
        </div>
      </div>
    </div>
  );
}

export default App;

关键修改说明

  • 事件回调修正:将onClick改为箭头函数传递,确保点击时才触发处理函数
  • 状态不可变性:创建新的行和节点对象修改状态,避免直接修改原对象
  • 遍历逻辑修复:正确遍历二维数组,定位目标单元格
  • 语义化优化:将isMousePressed重命名为isWall,更贴合功能需求
  • 性能优化:用useState初始化函数创建初始网格,避免重复执行
  • 添加key属性:解决React列表渲染的key警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 09:10:54