使用React时,要修复useEffect缺少依赖项错误

时间:2020-01-02 17:43:39

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

由于某种原因,我似乎无法理解这个错误; 我已经研究过回调,包括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;

我基本上是在制作Nodes组件的网格; 我必须使用useEffect,因为我试图只使用箭头函数和钩子,并且没有类/ react组件,这就是为什么我不能使用类似componentWillMount的原因。

3 个答案:

答案 0 :(得分:4)

您需要将使用的对象传递给您,将getGrid函数传递给useEffect挂钩以删除警告消息。

就像下面这样:

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

T.J. Crowder的其他建议,将useCallback用于getGrid。您可以按照以下步骤进行操作:

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

在此处进一步阅读:

  1. useEffect hook
  2. useCallback hook

您需要对代码中的getInitGrid进行同样的操作。

我希望这会有所帮助!

答案 1 :(得分:1)

正如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;

答案 2 :(得分:0)

Pathfinder中的大多数内容是静态的,应将其移到其模块之外;这样也可以解决您遇到的useEffect问题。所有START_NODE_ROW等const,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,第二个是在{之外定义的{1}}。)