将函数传递给自定义钩子时,如何修复useEffect中的无限循环



我正在尝试创建一个'useApi'钩子,它接受一个返回promise的函数。在我当前的实现中,我收到了关于在useEffect钩子中不包括依赖项的警告,即我传递给它的API promise函数。然而,如果我将其包括在依赖项中,它会导致无限循环。

我看了很多问题,但似乎解决不了。

请在这里找到我的样本:Codesandbox

问题是fetchData函数有两个依赖项,它们一直在变化:stateapiCall

state一直在更改,因为您更新了fetchData函数本身内部的状态
问题的解决方案是从setState函数本身获得状态,如下所示:

const fetchData = React.useCallback(() => {
setState((state) => {
return { ...state, loading: true, response: undefined };
});
apiCall()
.then((response) => {
setState((state) => {
return { ...state, response, loading: false };
});
})
.catch((err) => {
setState({ loading: false, response: undefined, error: err });
});
}, [apiCall]);

通过这种方式,您可以删除state依赖项。

apiCall也一直在变化,因为每次重新渲染组件时都会重新创建函数
要解决此问题,需要将useApi回调封装在useCallback钩子中:

const [{ error, loading, response }, fetchData, reset] = useApi(
React.useCallback(() => randomNumberApi(max), [max])
);

现在,您可以在不引起无限循环的情况下拥有useEffect依赖项:

React.useEffect(() => {
if (max) {
fetchData();
}
}, [fetchData, max]);

完整代码的CodeSandbox。

Ciao,要删除警告,只需要删除useEffect上的括号,如:

React.useEffect(() => {
if (max) {
fetchData();
}
}); // remove brackets

现在的问题是,每当App.js更改其状态时,都会调用useEffect(我的意思是总是这样,因为fetchData更改了App.js的状态(,结果是一个无限循环。

为了解决这个问题,你可以用这种方式使用useRef

import React, { useRef } from "react";
...
const firstLoad = useRef(true);
React.useEffect(() => {
if (max && firstLoad.current) {
fetchData();
}
firstLoad.current = false;
});

并且fetchData()将仅被调用一次(在第一次加载时(。

这里修改了你的代码沙盒。

相关内容

  • 没有找到相关文章

最新更新