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

React战舰游戏useEffect添加newLayout依赖触发无限重渲染如何修复?

React战舰游戏useEffect依赖警告修复方案

问题根源

你出现这个问题的核心原因是newLayout变量的声明位置错误,触发了渲染死循环:

  • 原代码控制台抛出的警告如下:

React Hook useEffect has a missing dependency: 'newLayout'. Either include it or remove the dependency array react-hooks/exhaustive-deps

  • newLayout = [...layout]写在组件顶层,每次组件渲染都会生成一个全新的数组引用
  • 如果你把它加入useEffect依赖数组,每次渲染都会触发useEffect执行,useEffect内部调用setLayout更新layout状态后会再次触发组件渲染,形成无限循环,最终导致应用崩溃
  • 而不加入依赖的话,就会触发上述的缺失依赖警告

修复方案

所有布局生成用到的临时变量全部放到useEffect内部,不需要依赖外部的layout和newLayout变量,修复后的代码如下:

const ComputerBoard = ({ COLUMNS, ROWS }) => {
  const [layout, setLayout] = useState(new Array(ROWS * COLUMNS).fill('empty'));

  useEffect(() => {
    // 新布局数组移到useEffect内部初始化
    const newLayout = new Array(ROWS * COLUMNS).fill('empty');

    const checkIfShipFits = (isHorizontal, spaces, i) => {
      let temp = 0;
      const x = i % ROWS;
      const y = Math.floor(i / COLUMNS);

      for (let n = 0; n < spaces; n += 1) {
        if (isHorizontal) {
          if (x + spaces < COLUMNS && newLayout[i + n] !== 'ship') {
            temp += 1;
          }
        }
        if (!isHorizontal) {
          if (y + spaces < ROWS && newLayout[i + COLUMNS * n] !== 'ship') {
            temp += 1;
          }
        }
      }

      return temp === spaces;
    };

    const generateComputerLayout = () => {
      const totalShips = computerShipsAvaibles;
      const boardSize = ROWS * COLUMNS;

      // 遍历所有战舰类型
      for (let j = 0; j < totalShips.length; j += 1) {
        // 遍历对应类型战舰的生成数量
        for (let k = 0; k < totalShips[j].amount; k += 1) {
          let i = generateRandomIndex(boardSize);
          const isHorizontal = generateRandomDirection();

          while (!checkIfShipFits(isHorizontal, totalShips[j].spaces, i)) {
            i = generateRandomIndex(boardSize);
          }

          for (let l = 0; l < totalShips[j].spaces; l += 1) {
            if (isHorizontal) newLayout[i + l] = 'ship';
            if (!isHorizontal) newLayout[i + COLUMNS * l] = 'ship';
          }
        }
      }

      setLayout(newLayout);
    };

    generateComputerLayout();
  }, [COLUMNS, ROWS]);

  return (
    <div>
      <h3>Computer</h3>
      <div className='board'>
        {layout.map((square, index) => (
          <div
            // eslint-disable-next-line react/no-array-index-key
            key={index}
            className={`square ${square} computer`}
          />
        ))}
      </div>
    </div>
  );
};

核心修改说明

  • 删除了组件顶层的newLayout声明,避免生成额外的外部依赖,同时移除了原代码中无用的随机数生成语句
  • 在useEffect内部初始化空白布局数组,所有生成逻辑用到的变量都在effect作用域内,不需要依赖外部状态
  • 修复后useEffect的依赖只有COLUMNS和ROWS,完全符合hooks规则,既不会触发警告,也不会出现死循环,只会在组件挂载、或者行列数变化的时候重新生成电脑方战舰布局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:45:03