在 React Native 中卸载组件期间,清理功能在 UseEffect Hook 中不起作用

时间:2021-07-05 11:34:57

标签: javascript reactjs react-native react-hooks

在 React Native 应用程序中,A 中有两个组件 BApp.js,它们与 k 状态更改切换。

App.js

...

const App = () => {
      const [ k, setK ] = useState(false);

      const toggleK = () => setK(!k);

      if(k) {
            return <A />;
      }else {
            return <B toggleK={toggleK} />;
      }
};
...

A 中,setIntervaluseffect 中初始化。它每 10 秒调用一次异步函数。但是当它在 K 中的 App.js 状态更改时卸载时,不会运行清理功能(没有记录 A unmounting...),clearInterval 也是如此。

我在这里做错了什么?

...

const A = () => {
      const [ someState, setSomeState ] = useState(...);

      let timer;

      useEffect(() => {
            if(!timer) {
                  timer = setInterval(async () => await run_async_func(), 10000);
            }

            return () => {
                  console.log('A unmounting...');
                  clearInterval(timer);
            };
      }, [ someState ]);
};
...

3 个答案:

答案 0 :(得分:0)

用 useRef() 试试这个。

const A = () => {
 const timer = useRef()
  const [ someState, setSomeState ] = useState(...);


  useEffect(() => {
        if(!timer) {
              timer.current = setInterval(async () => await run_async_func(), 10000);
        }

        return () => {
              console.log('A unmounting...');
              clearInterval(timer.current);
        };
  }, [ someState ]);
};

答案 1 :(得分:0)

已解决问题

  • 导致问题的原因是什么?

A.忽略了 someState 依赖项数组中的 useEffect。基本上,只有在依赖数组中的任何变量发生变异时,更清洁的函数才会运行。因此,我使用了另一个没有任何依赖项的 useEffect(见下文)。感谢@TayyabMazhar 指出这一点

...
const A = () => {
      const [ someState, setSomeState ] = useState(...);

      let timer;

      useEffect(() => {
            if(!timer) {
                  timer = setInterval(async () => await run_async_func(), 10000);
            }
      }, [ someState ]);

      useEffect(() => {
            return () => {
                 console.log('A unmounting...');
                 clearInterval(timer);
            };
      }, []);
};
...

答案 2 :(得分:-1)

你可以使用这个钩子我创建了这个

    import { useEffect, useRef } from 'react';

export const useInterval = (callback: () => void, delay: number): void => {
    const savedCallback = useRef(null);

    // Remember the latest callback.
    useEffect(() => {
        savedCallback.current = callback;
    }, [callback]);

    // Set up the interval.
    useEffect(() => {
        function tick() {
            savedCallback.current();
        }
        if (delay !== null) {
            const id = setInterval(tick, delay);
            return () => clearInterval(id);
        }
    }, [delay]);
};