即使存在依赖关系,如何运行 useEffect 一次?为什么 ESLint 会抱怨它?

Moh*_*gih 8 reactjs react-hooks use-effect

考虑以下示例:

const userRole = sessionStorage.getItem('role');
const { data, setData, type, setTableType } = useTable([]);

useEffect(() => {
  const getData = async () => {
    // fetch some data from API
    const fetchedData = await axios('..');
    
    if (userRole === 'admin') {
     setData([...fetchedData, { orders: [] }]);
    } else {
     setData(fetchedData);
    }
    
    if (type === '1') {
     setTableType('normal');
    }
  };
  getData();
}, []);
Run Code Online (Sandbox Code Playgroud)

我只想在安装时运行此效果,仅此而已,我不在乎userRole或是否setData已更改!

所以,现在我的问题是:

  1. 为什么 ESLint 抱怨userRole在依赖项数组中丢失?它甚至不是一个国家!
  2. 为什么 ESLint 抱怨setData在依赖项数组中缺少它是不是它总是相同的引用或者它是否会改变?
  3. 如何在不打扰 linter 的情况下实现我想要的?还是我应该直接打过去// eslint-disable-line react-hooks/exhaustive-deps?或者这绝对是野蛮的?
  4. 为什么这表明我的代码中存在错误?我只想使用最初可用的任何内容运行此效果一次。

编辑:让我重新表述这个问题,如果这些变量发生变化而我不关心它们的新值怎么办?尤其type是在同一文件的不同位置进行更新时。我只想读取初始值并运行一次 useEffect 如何实现?

反应钩子/详尽的deps警告

Gus*_*ira 5

另一个解决方案是创建一个用于初始化的钩子(运行一次)。

import { useState } from 'react';

export const useInit = initCallback => {
  const [initialized, setInitialized] = useState(false);

  if (!initialized) {
    initCallback();
    setInitialized(true);
  }
};
Run Code Online (Sandbox Code Playgroud)

然后在你的 React 组件上使用它:

useInit(() => {
  // Your code here will be run only once
});
Run Code Online (Sandbox Code Playgroud)


Roh*_*wal 1

Linting 是分析代码潜在错误的过程。现在,当我们谈论为什么会出现 lint 错误时,我们需要了解规则是通过牢记特定功能的理想用例来设置的。

在 useEffect 挂钩的情况下,一般概念是,如果我们有一个可能会更改或可能导致逻辑流更改的值,则所有这些都应该进入依赖项数组。

因此,数据是第一个进入的候选者。 userRole 的情况类似,因为它被用来控制逻辑流,而不仅仅是作为一个值。

我建议使用 linter 建议来忽略错误。

  • 由于您使用的是自定义挂钩,因此我不确定如何使 linter 满意,但仅运行一次。然而,存在一种黑客方法(useRef)来保持数组非空并运行一次,从而保持 linter 满意。尽管我建议反对。 (2认同)