使用React 16.8.6(在之前的版本16.8.3上很好),当我试图阻止fetch请求上的无限循环时,我得到了这个错误:

./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

我一直无法找到一个解决办法来停止这个无限循环。我想远离使用useReducer()。我确实找到了关于'筋疲力尽-deps' lint规则#14920的讨论[ESLint]反馈,其中一个可能的解决方案是,如果你认为你知道你在做什么,你可以总是// ESLint - disabled -next-line react-hooks/详尽-deps。我对我正在做的事情没有信心,所以我还没有尝试实现它。

我有这个当前的设置,React钩子useEffect连续运行永远/无限循环,唯一的评论是关于useCallback(),我不熟悉。

我目前如何使用useEffect()(我只想在开始时运行一次,类似componentDidMount()):

useEffect(() => {
    fetchBusinesses();
  }, []);
const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };

当前回答

如果在useEffect中使用的变量是在组件内部定义的,或者是作为道具传递给组件的,则会发生此警告。因为你在同一个组件中定义了fetchBusinesses(),而eslint遵循这一规则,你必须将它传递给依赖数组。但在您的情况下,只传递[]也可以

在这种情况下,它将工作,但如果fetchBusinesses在函数中使用setState,并且调用它将重新呈现组件,因此您的fetchBusinesses将改变,因此useEffect将运行,这将创建一个无限循环。因此,仅仅盲目地遵循eslint可能会导致额外的错误。

用例解决方案让eslint满意,使用useCallback和[]。

const memoizedFetchBusinesses=useCallback(
        fetchBusinesses,
        [] // unlike useEffect you always have to pass a dependency array
       )

当组件第一次呈现时,在内存中创建一个名为fetchBusinessess的函数,并创建memoizedFetchBusinesses变量,该变量也在内存中引用相同的函数。

在第一次渲染之后,一个被称为fetchbusiness的函数将再次被创建,但这一次在不同的内存位置,因为我们在useCallback中有[],memoizedFetchBusinesses将在相同的内存中给你原始的fetchBusinesses函数。这里的useCallback将为您提供在组件的第一次呈现中创建的相同的函数引用。

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

相反,你可以这样定义函数

const fetchBusinesses = useCallback(() => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  },[]);

然后在useEffect中

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

其他回答

./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

这不是一个JavaScript/React错误,而是一个ESLint (ESLint -plugin- React -hooks)警告。

它告诉你这个钩子依赖于fetchBusinesses函数,所以你应该把它作为一个依赖项传递。

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

如果函数在组件中声明,则可能导致在每次渲染时调用该函数:

const Component = () => {
  /*...*/

  // New function declaration every render
  const fetchBusinesses = () => {
    fetch('/api/businesses/')
      .then(...)
  }

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

  /*...*/
}

因为每次用新的引用重新声明函数时。

正确的做法是:

const Component = () => {
  /*...*/

  // Keep the function reference
  const fetchBusinesses = useCallback(() => {
    fetch('/api/businesses/')
      .then(...)
  }, [/* Additional dependencies */])

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

  /*...*/
}

或者只是在useEffect中定义函数。

更多:[ESLint]关于'枯竭-deps' lint规则#14920的反馈

使用UseEffect fetchBusinesses调用UseEffect()中的function declare,在调用函数名后声明一个const变量,

useEffect(()=>{
const fetchBusinesses=()=>{
   console.log(useeffect fetchbussinesses functions)
}
 fetchBusinesses();
},[declare the variable used in useeffect hooks ])

在项目中禁用此警告

将这个"react-hooks/ exhaustion -deps": "off"添加到.eslintrc.js文件中

您可以删除第二个参数类型数组[],但fetchBusinesses()也将在每次更新时被调用。如果愿意,可以在fetchBusinesses()实现中添加IF语句。

React.useEffect(() => {
  fetchBusinesses();
});

另一个方法是在组件外部实现fetchBusinesses()函数。如果有的话,不要忘记将任何依赖参数传递给fetchBusinesses(依赖项)调用。

function fetchBusinesses (fetch) {
  return fetch("theURL", { method: "GET" })
    .then(res => normalizeResponseErrors(res))
    .then(res => res.json())
    .then(rcvdBusinesses => {
      // some stuff
    })
    .catch(err => {
      // some error handling
    });
}

function YourComponent (props) {
  const { fetch } = props;

  React.useEffect(() => {
    fetchBusinesses(fetch);
  }, [fetch]);

  // ...
}

搜索关键字以了解有关每个警告的更多信息。 要忽略,在前一行添加// eslint-disable-next-line。

例如:useEffect中使用的函数正在引起警告

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

要忽略警告,我们只需在警告行之前添加“// eslint-disable-next-line”。

useEffect(() => { handleConnectWallet (); / / eslint-disable-next-line },[]);