为什么在 React 中使用清理功能(useEffect)不清除 setTimeOut?

Why does the setTimeOut not being cleared by using clean up function in React (useEffect)?

我想在卸载组件时清除所有 setTimeOut。 即使我使用 clearTimeOut 作为清理函数,但错误仍然存​​在:"Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function"

useEffect(() => {
     const timeOut = {timeout1: ()=>setTimeout(() => setProgress((preV) => preV + 15), [
        550,
      ]),timeout2 : ()=> setTimeout(() => setMessage("All most done"), [500])}
      timeOut.timeout1();
      timeOut.timeout2();


    return () => {
      clearTimeout(timeOut.timeout1);
      clearTimeout(timeOut.timeout2);
    };
  }, [progress,message]);

有谁知道如何解决这个问题?如有任何帮助,我们将不胜感激!

timeout1 不是存储 setTimeout 的返回值,即 timerId,而是存储执行超时的函数的引用

您可以使用 Immediately invoked functions 以立即执行超时的方式编写代码,以便 timeout1timeout2 具有 timerIds

useEffect(() => {
     const timeOut = {
           timeout1: (()=>setTimeout(() => setProgress((preV) => preV + 15), 550))(),
           timeout2 : (()=> setTimeout(() => setMessage("All most done"), 500))()
     }



    return () => {
      clearTimeout(timeOut.timeout1);
      clearTimeout(timeOut.timeout2);
    };
  }, [progress,message]);

但是你可以简单地 运行 超时而不用将它们写成 IIFE

useEffect(() => {
     const timeOut = {
           timeout1: setTimeout(() => setProgress((preV) => preV + 15), 550),
           timeout2 : ()=> setTimeout(() => setMessage("All most done"), 500)
     }



    return () => {
      clearTimeout(timeOut.timeout1);
      clearTimeout(timeOut.timeout2);
    };
  }, [progress,message]);

如何使用一个局部变量来跟踪组件是否已安装。

useEffect(() => {
  let run = true;

  const timeOut = {
    timeout1: () => setTimeout(() => setProgress((preV) => preV + 15), [550]),
    timeout2: () => setTimeout(() => setMessage('All most done'), [500]),
  };

  if (run) {
    timeOut.timeout1();
    timeOut.timeout2();
  }

  return () => {
    clearTimeout(timeOut.timeout1);
    clearTimeout(timeOut.timeout2);
    run = false;
  };
}, [progress, message]);