自定义反应挂钩导致无限循环

时间:2020-05-06 11:33:03

标签: reactjs redux async-await react-hooks

我有一个自定义的抓取钩子:

export const useFetch = (url: string) => {
  const [response, setResponse] = useState<any>(null);
  const [error, setError] = useState<any>(null);

  const fetchList = (url: string) => {
    return API.get(AMPLIFY_ENPOINTS.default, url, { response: true });
  };

  useEffect(() => {
    const fetchFunc = async () => {
      try {
        const fetchResponse = await fetchList(url);
        setResponse(fetchResponse.data);
      } catch (error) {
        setError(error);
      }
    };
    fetchFunc();
  }, [url]);

  return { response, error };
};

然后在组件中使用它:

const fetchOrders = useFetch(apiUrl);
useEffect(() => {
  const { response, error } = fetchOrders;
  if (error) setError(error);
  if (response) {...}
}, [fetchOrders]);

这会导致无限循环,我该如何解决呢?

2 个答案:

答案 0 :(得分:2)

由于您每次都返回一个新创建的对象,因此fetchOrder引用会在每次重新渲染时保持更改,因此当您在useEffect中调用setError时,它将触发无限循环。

与其添加fetchOrders作为依赖项,不如分别添加responseerror

const { response, error } = useFetch(apiUrl);
useEffect(() => {
  const  = fetchOrders;
  if (error) setError(error);
  if (response) {...}
}, [response, error]);

答案 1 :(得分:0)

此行负责

return { response, error };

当然,他在犯罪方面的搭档是第二个useEffect中的[fetchOrders]依赖项数组。

第一行返回一个新对象,因此fetchOrders始终是一个新值。

考虑了您的代码后,我得出结论,您可能根本不需要第二个useEffect。

// the useFetch only re-fetches when url changes
const { response, error } = useFetch(url);

// use response directly, you don't need to re-set the error nor the response in your component.

但是,如果要对响应产生副作用,则可以考虑升级useFetch挂钩以接受回调参数,并升级具有响应依赖项的useEffect。