简体   繁体   English

React Hooks useCallback 依赖无限循环

[英]React Hooks useCallback dependency infinite loop

I'm currently fetching my data once when the component mounts, then whenever the user clicks a button.我目前在组件安装时获取我的数据一次,然后在用户单击按钮时获取。 I want however to stop the button from fetching if a request is in progress, that's why I'm updating the isFetching state.但是,如果请求正在进行,我想停止按钮获取,这就是我更新isFetching state 的原因。

However, I need to add the isFetching to the useCallback dependency to remove the warning and if I do, an infinite fetch loop is triggered.但是,我需要将isFetching添加到useCallback依赖项以删除警告,如果这样做,则会触发无限获取循环。

Here's my code:这是我的代码:

import { useCallback, useEffect, useRef, useState } from 'react';

export const MyComponent = () => {
  const isMounted = useRef(true);
  const [isFetching, setIsFetching] = useState(false);
  
  const [data, setData] = useState(null);
  
  // Can also be called from the button click
  const getMyData = useCallback(() => {
    if (isFetching) return;
    setIsFetching(true);
    fetch('get/my/data')
      .then((res) => {
        if (isMounted.current) {
          setData(res.data);
        }
      })
      .catch((err) => {
        if (isMounted.current) {
          setData("Error fetching data");
        }
      })
      .finally(() => {
        if (isMounted.current) {
          setIsFetching(false);
        }
      });
  }, []); // isFetching dependency warning as is, if added then infinite loop

  useEffect(() => {
    isMounted.current = true;
    getMyData();
    return () => {
      isMounted.current = false;
    };
  }, [getMyData]);

  return (
    <div>
        <button onClick={getMyData}>Update data</button>
        <p>{data}</p>
    </div>
  );
};

I understand that there are multiple questions like this one, but I couldn't remove the warning or infinite loop while still checking if the component is mounted.我知道有多个像这样的问题,但我无法删除警告或无限循环,同时仍在检查组件是否已安装。

Here are some examples: example-1 , example-2以下是一些示例: example-1example-2

Convert isFetching to a ref, so it's value won't be a dependency of the function:isFetching转换为 ref,因此它的值不会是 function 的依赖项:

 const { useCallback, useEffect, useRef, useState } = React; const MyComponent = () => { const isMounted = useRef(true); const isFetching = useRef(false); const [data, setData] = useState([]); // Can also be called from the button click const getMyData = useCallback(() => { console.log('call'); if (isFetching.current) return; isFetching.current = true; fetch('https://cat-fact.herokuapp.com/facts').then(res => res.json()).then(res => { if (isMounted.current) { setData(res); } }).catch((err) => { if (isMounted.current) { setData("Error fetching data"); } }).finally(() => { if (isMounted.current) { isFetching.current = false; } }); }, []); // isFetching dependency warning as is, if added then infinite loop useEffect(() => { isMounted.current = true; getMyData(); return () => { isMounted.current = false; }; }, [getMyData]); return ( <div> <button onClick={getMyData}>Update data</button> <ul> { data.map(({ _id, text }) => ( <li key={_id}>{text}</li> )) } </ul> </div> ); }; ReactDOM.render( <MyComponent />, root );
 <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="root"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM