【问题标题】:Custom react hook causes infinite loop自定义反应钩子导致无限循环
【发布时间】:2020-05-06 11:33:03
【问题描述】:

我有一个自定义提取钩子:

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]);

这会导致无限循环,我应该如何修复它?

【问题讨论】:

    标签: reactjs redux async-await react-hooks


    【解决方案1】:

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

    不要将fetchOrders添加为依赖项,而是分别添加responseerror

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

    【讨论】:

    • 次要评论,但可能会使某些人感到困惑:您的第一行 useEffect 不再有意义,是吗?据我了解,您已经在第一行代码中将 useFetch 响应解构为响应和错误,并且变量 fetchOrders 从未初始化
    【解决方案2】:

    是这条线负责这个

    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。

    【讨论】:

      【解决方案3】:

      在您的组件中,尝试将输入包装在 useMemo 中。

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

      否则,apiUrl 是一个局部变量,每次功能组件运行时都会重新创建,从而导致无限循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-04-10
        • 2020-03-25
        • 2023-01-15
        • 2020-10-27
        • 2021-12-30
        • 2021-03-11
        • 1970-01-01
        相关资源
        最近更新 更多