setTimeOut在React中的最佳实践

1,994 阅读1分钟

当我们使用 setTimeout 时,通常我们不必去考虑清理它。但是,将其引入 React 会产生一些棘手的偶发事件。

这种情况时有发生,因为当我们想在某个时间点之后对数据进行操作,但那时组件可能已经被卸载了,但 setTimeout 仍在试图运行。所以你可能会遇到组件交互被强制恢复、内存泄漏等情形。

那么我们来清晰地使用 setTimeOut() 吧!

总体来说是我们可以追踪代码中创建的超时并用 useEffect 来清理它们。

一个简单的案例可以这样:在CodeSandBox中运行

// App.tsx
import { useState, useEffect } from "react";

export default function App() {
  const [isLoading, setIsLoading] = useState(false);
  useEffect(() => {
    setIsLoading(true);
    const timer = setTimeout(() => {
      setIsLoading(false);
    }, 3000);
    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <>{isLoading ? <span>Loading...</span> : <p>I'm fully loaded now</p>}</>
  );
}

当然,我们也可以使用 参照(reference),useRef() 来清除定时器。

import { useState, useEffect, useRef } from "react";

export default function App() {
  const [isLoading, setIsLoading] = useState(false);
  const timeoutRef = useRef(0);

  useEffect(() => {
    setIsLoading(true);
    timeoutRef.current = window.setTimeout(() => {
      setIsLoading(false);
    }, 3000);
    return () => clearInterval(timeoutRef.current);
  }, []);

  return (
    <>{isLoading ? <span>Loading...</span> : <p>I'm fully loaded now</p>}</>
  );
}

参考文献:React cleaner use of setTimeout (daily-dev-tips.com)