【问题标题】:Using React, want to fix useEffect has a missing dependency error使用 React,想修复 useEffect has a missing dependency 错误
【发布时间】:2020-04-21 08:59:21
【问题描述】:

由于某种原因,我似乎无法理解这个错误; 我已经查看了回调,包括useEffect 中的代码,但它对我不起作用(或者我做错了)。

代码如下:

import React, { useEffect, useState } from "react";
import "../css/main.css";
import Node from "./node";

const Pathfinder = () => {
  const START_NODE_ROW = 10;
  const START_NODE_COL = 15;
  const FINISH_NODE_ROW = 10;
  const FINISH_NODE_COL = 35;

  useEffect(() => {
    getGrid();
  }, []);

  const [grid, setGrid] = useState([]);

  const getGrid = () => {
    setGrid(getInitGrid());
  };

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

  const createNode = (col, row) => {
    return {
      col,
      row,
      isStart: row === START_NODE_ROW && col === START_NODE_COL,
      isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
      distance: Infinity,
      isVisited: false,
      isWall: false,
      previousNode: null
    };
  };

  return (
    <main id="Pathfinder">
      {grid.map((row, rowIdx) => {
        return (
          <div key={rowIdx}>
            {row.map((node, nodeIdx) => {
              const { row, col, isFinish, isStart } = node;
              return (
                <Node
                  key={nodeIdx}
                  col={col}
                  isFinish={isFinish}
                  isStart={isStart}
                  row={row}
                ></Node>
              );
            })}
          </div>
        );
      })}
    </main>
  );
};

export default Pathfinder;

我基本上是在制作节点组件的网格; 我必须使用useEffect,因为我试图只使用箭头函数和钩子,而没有类/反应组件,这就是为什么我不能使用像componentWillMount 这样的东西。

【问题讨论】:

  • 试着把useeffect放在你的setGrid函数下面
  • getGrid 对于调用setGrid 的函数来说,是一个真的令人困惑的名称。也许setInitialGrid

标签: javascript reactjs dependencies react-hooks use-effect


【解决方案1】:

您需要将使用的对象(在您的情况下是 getGrid 函数传递给 useEffect 挂钩以删除警告消息。

就像下面这样:

useEffect(() => {
   getGrid();
}, [getGrid]);

来自T.J. Crowder 的其他建议,将useCallback 用于getGrid。你可以这样做:

const getGrid = useCallback(() => {
    setGrid(getInitGrid());
}, [getInitGrid]);

在此处进一步阅读:

  1. useEffect hook
  2. useCallback hook

您需要在代码中对 getInitGrid 执行相同操作。

我希望这会有所帮助!

【讨论】:

  • getGrid 也应该包含在 useCallback 中。
  • @T.J.Crowder 没错,刚刚更新了我的答案,谢谢。
  • 无需将setGrid 列为getGrid 的一个部门。状态设置函数是guaranteed to be stable
【解决方案2】:

正如 TJ 提到的,将函数 getInitGridcreateNode 移到组件之外是最好的举措。按照您现在的方式,函数将在每次渲染时重新定义,这不是必需的,因为它们与您的组件状态没有直接关联。

此外,useState 钩子可以使用 lazy intitial state,这意味着您可以为初始状态参数传递一个函数,而您根本不需要 useEffect 钩子。

这是我最终得到的结果:

import React, { useState } from "react";
import "../css/main.css";
import Node from "./node";

const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 10;
const FINISH_NODE_COL = 35;

const createNode = (col, row) => {
  return {
    col,
    row,
    isStart: row === START_NODE_ROW && col === START_NODE_COL,
    isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
    distance: Infinity,
    isVisited: false,
    isWall: false,
    previousNode: null
  };
};

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

const Pathfinder = () => {

  const [grid, setGrid] = useState(getInitGrid);

  return (
    <main id="Pathfinder">
      {grid.map((row, rowIdx) => {
        return (
          <div key={rowIdx}>
            {row.map((node, nodeIdx) => {
              const { row, col, isFinish, isStart } = node;
              return (
                <Node
                  key={nodeIdx}
                  col={col}
                  isFinish={isFinish}
                  isStart={isStart}
                  row={row}
                ></Node>
              );
            })}
          </div>
        );
      })}
    </main>
  );
};

export default Pathfinder;

【讨论】:

    【解决方案3】:

    Pathfinder 中的大部分内容是静态的,应该将其移到其模块之外;这也将具有处理您遇到的useEffect 问题的效果。所有START_NODE_ROW 等常量、getInitGridcreateNode 都是静态的,无需每次都重新创建它们。我还将getGrid 包装在useCallback 中,并且可能会重新排序轻微,以便仅在定义后使用,但这主要是针对人类读者,而不是编译器/JavaScript 引擎:

    import React, { useEffect, useState } from "react";
    import "../css/main.css";
    import Node from "./node";
    
    const START_NODE_ROW = 10;
    const START_NODE_COL = 15;
    const FINISH_NODE_ROW = 10;
    const FINISH_NODE_COL = 35;
    
    const getInitGrid = () => {
      const grid = [];
      for (let row = 0; row < 20; row++) {
        const currentRow = [];
        for (let col = 0; col < 50; col++) {
          currentRow.push(createNode(col, row));
        }
        grid.push(currentRow);
      }
      return grid;
    };
    
    const createNode = (col, row) => {
      return {
        col,
        row,
        isStart: row === START_NODE_ROW && col === START_NODE_COL,
        isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
        distance: Infinity,
        isVisited: false,
        isWall: false,
        previousNode: null
      };
    };
    
    const Pathfinder = () => {
    
      const [grid, setGrid] = useState([]);
    
      const getGrid = useCallback(() => {
        setGrid(getInitGrid());
      }, []);
    
      useEffect(() => {
        getGrid();
      }, []);
    
      return (
        <main id="Pathfinder">
          {grid.map((row, rowIdx) => {
            return (
              <div key={rowIdx}>
                {row.map((node, nodeIdx) => {
                  const { row, col, isFinish, isStart } = node;
                  return (
                    <Node
                      key={nodeIdx}
                      col={col}
                      isFinish={isFinish}
                      isStart={isStart}
                      row={row}
                    ></Node>
                  );
                })}
              </div>
            );
          })}
        </main>
      );
    };
    
    export default Pathfinder;
    

    另外,getGrid 很小并且只使用一次。对我来说,不值得把它分解成自己的功能:

    import React, { useEffect, useState } from "react";
    import "../css/main.css";
    import Node from "./node";
    
    const START_NODE_ROW = 10;
    const START_NODE_COL = 15;
    const FINISH_NODE_ROW = 10;
    const FINISH_NODE_COL = 35;
    
    const getInitGrid = () => {
      const grid = [];
      for (let row = 0; row < 20; row++) {
        const currentRow = [];
        for (let col = 0; col < 50; col++) {
          currentRow.push(createNode(col, row));
        }
        grid.push(currentRow);
      }
      return grid;
    };
    
    const createNode = (col, row) => {
      return {
        col,
        row,
        isStart: row === START_NODE_ROW && col === START_NODE_COL,
        isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
        distance: Infinity,
        isVisited: false,
        isWall: false,
        previousNode: null
      };
    };
    
    const Pathfinder = () => {
    
      const [grid, setGrid] = useState([]);
    
      useEffect(() => {
        setGrid(getInitGrid());
      }, []);
    
      return (
        <main id="Pathfinder">
          {grid.map((row, rowIdx) => {
            return (
              <div key={rowIdx}>
                {row.map((node, nodeIdx) => {
                  const { row, col, isFinish, isStart } = node;
                  return (
                    <Node
                      key={nodeIdx}
                      col={col}
                      isFinish={isFinish}
                      isStart={isStart}
                      row={row}
                    ></Node>
                  );
                })}
              </div>
            );
          })}
        </main>
      );
    };
    
    export default Pathfinder;
    

    (您不必将setGridgetInitGrid 声明为依赖项,因为第一个是来自React 的状态设置器函数guaranteed to be stable,第二个是在Pathfinder 之外定义的。)

    【讨论】:

      猜你喜欢
      • 2021-09-04
      • 2021-11-23
      • 2012-08-04
      • 2021-03-23
      • 2022-01-11
      • 2020-04-15
      • 2014-04-28
      • 2021-05-05
      • 1970-01-01
      相关资源
      最近更新 更多