使用带有依赖项的 useEffect 钩子时,清理功能何时触发?

IT技术 javascript reactjs react-hooks
2021-05-04 22:47:58

我正在使用 useEffect 来显示 UI 加载...但仅在 250 毫秒之后。它有效......但我真的不明白为什么,特别是如何以及何时 useEffect 调用返回的函数(清除超时)。

嗯......我不确定这是否完美。有时应该出现“正在加载...”消息,但事实并非如此。

 const [loadingAfterShortTime, setLoadingAfterShortTime] = useState(false);

 useEffect(() => {
  setLoadingAfterShortTime(bool => false);
  if (myDepandanceToTrigTheLoadingWord === true) {
    const id = setTimeout(() => {
      setLoadingAfterShortTime(bool => true);
    }, 250);
    return () => {
      clearTimeout(id);
    };
  }
}, [myDepandanceToTrigTheLoadingWord]);
3个回答

@Powell Ye 提供的解释很好,但是在谈到重新渲染时(例如,当props更改时)有一些错误的信息

考虑一些简单的组件,如下所示

    useEffect( () => {
        console.log('Effect is applied')
        //some logic
        return () => {
            console.log('cleaning up')
            //cleanup logic
        }
    })
    return (<>
        {console.log('rendering...')}
     </>)

说在你可能认为的变化中传递的props

  1. '打扫干净'
  2. 新props
  3. '渲染...'
  4. '应用效果'

但是,实际上会发生以下情况

  1. 新props
  2. '渲染...'
  3. '打扫干净'
  4. '应用效果'

也就是说,清理功能在新的渲染/绘画之后运行,但应用“新”效果之前文档可能对此有点含糊不清

在执行下一个效果之前清除上一个效果

这样做是出于性能原因 => 以便渲染不会延迟(有时对我来说也令人沮丧)

以下是所涉及时间的概述:

  • useEffect在初始渲染时调用,并且每当它依赖的任何值发生变化时都会调用。通常,它会在渲染完成后触发。如果您从基于类的组件的角度考虑它,则等效于componentDidMount方法。
  • useEffect在组件从 UI 中移除或即将重新渲染(以避免内存泄漏)之前调用从内部返回的函数在执行下一个效果之前,总是先清除上一个效果。它保证在任何新渲染之前运行。等价的将是componentWillUnmount

例子

让我们假设有一个useEffect由 props(传递给我们的组件)+一个清理函数组成的很少依赖项。在第一次渲染时,会发生以下情况:

  • 一旦安装了组件,效果体中的代码就会运行;
  • 清理功能保持原状,准备在组件重新渲染/从屏幕上移除之前运行。

现在让我们想象一下触发重新渲染的事情。由于它被列为某些useEffect依赖,因此效果将重新执行如下:

  • 渲染完成后执行清理函数;
  • 紧接着,效果体内部的代码将运行;
  • 再次创建新的清理函数,准备在组件重新渲染后/或从屏幕上移除之前执行。

根据react文档,

清理效果

清理功能在组件从 UI 中移除之前运行,以防止内存泄漏。此外,如果一个组件渲染多次(正如他们通常所做的那样),则在执行下一个效果之前会清除前一个效果。

效果时间

在开始新的更新之前,React 将始终刷新之前的渲染效果。

根据我对这两个引号的理解,在应用效果之后和卸载组件(从 UI 中删除)之前运行清理