【问题标题】:React Hook useEffect has a missing dependency when passing empty array as second argument将空数组作为第二个参数传递时,React Hook useEffect 缺少依赖项
【发布时间】:2020-05-17 23:18:28
【问题描述】:

我的功能组件中有以下 useEffect 挂钩,我只想使用一次(当组件挂载时)以便从 API 加载一些数据:

const Gear = () => {
  const [weaponOptions, setWeaponOptions] = useState([
    {
      key: "0",
      label: "",
      value: "null"
    }
  ]);
  const [weapon, setWeapon] = useState("null");

  useEffect(() => {
    console.log("Gear.tsx useEffect");

    const fetchWeaponsOptions = async (): Promise<void> => {
      const weaponsData = await getWeapons();
      const newWeaponOptions: DropdownOptionType[] = [
        ...weaponOptions,
        ...weaponsData.map(({ id, name }) => {
          return {
            key: id,
            label: name,
            value: id
          };
        })
      ];
      setWeaponOptions(newWeaponOptions);
    };

    fetchWeaponsOptions();
  }, []);

  // TODO add weapon dropdown on change, selected weapon state
  const handleWeaponChange = ({ value }: DropdownOptionType): void => {
    setWeapon(value);
  };

  return (
    <div>
      <h2>Gear:</h2>
      <Dropdown
        defaultValue={weapon}
        label="Weapon"
        name="weapon"
        options={weaponOptions}
        onChange={handleWeaponChange}
      />
    </div>
  );
};

React documentation note 指出,当您只希望效果在挂载和卸载时运行时,这是有效的做法:

如果你想运行一个效果并只清理一次(在挂载和 unmount),您可以传递一个空数组 ([]) 作为第二个参数。这 告诉 React 你的效果不依赖于 props 的任何值 或状态,因此它永远不需要重新运行。这不作为特殊处理 case — 它直接遵循依赖项数组的方式 有效。

但我收到以下 create-react-app linter 警告:

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

如果我将 weaponOptions 数组作为依赖项传递,则如果 weaponOptions 数组发生更改,则 useEffect 触发,从而导致无限循环,因为钩子本身会更改武器选项状态。如果我省略空数组参数,也会发生同样的事情。

这里的正确方法是什么?

【问题讨论】:

  • 会的,请告诉我们weaponOptions来自哪里
  • @DennisVash sry,将整个功能组件代码添加到最初的问题中以使事情更清晰

标签: javascript reactjs


【解决方案1】:

我只想使用一次(当组件挂载时)以便从 API 加载一些数据

因此根据你的逻辑,你不需要依赖组件的状态:

const INITIAL = [
  {
    key: '0',
    label: '',
    value: 'null'
  }
];

const App = () => {
  const [weaponOptions, setWeaponOptions] = useState(INITIAL);

  useEffect(() => {
    const fetchWeaponsOptions = async () => {
      const weaponsData = await getWeapons();
      const weaponsOptions = [
        ...INITIAL, // No state dependency needed
        ...weaponsData.map(({ id, name }) => {
          return {
            key: id,
            label: name,
            value: id
          };
        })
      ];
      setWeaponOptions(weaponsOptions);
    };

  }, []);

  return <></>;
};

但是,当您想使用一次useEffect 时,这是很常见的,这取决于状态,使用布尔引用,如下所示:

const App = () => {
  const [weaponOptions, setWeaponOptions] = useState(INITIAL);

  const isFirstFetch = useRef(true);

  useEffect(() => {
    const fetchWeaponsOptions = async () => {...}

    if (isFirstFetch.current) {
      fetchWeaponsOptions();
      isFirstFetch.current = false;
    }
  }, [weaponOptions]);

  return <></>;
};

【讨论】:

  • 这很有意义:)。非常感谢
【解决方案2】:

如您所见,这不是错误而是警告。 React 告诉您您在 weaponOptions 内使用 useEffect 但您没有将其作为依赖项传递。同样,这只是一个警告,您不必这样做。

【讨论】:

    猜你喜欢
    • 2022-06-12
    • 1970-01-01
    • 2021-07-28
    • 2022-11-23
    • 2021-02-23
    • 2019-10-24
    • 2020-10-26
    • 2020-03-07
    • 2020-02-25
    相关资源
    最近更新 更多