使用带依赖项的 useEffect 钩子时,什么时候触发清理功能?

When is the cleanup function triggered when using useEffect hook with dependencies?

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

嗯......我不确定这是否完美。有时应该显示 "Loading ..." 消息,但实际上没有。

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

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

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

  • useEffect 在初始渲染时调用,只要它依赖的任何值发生变化。一般来说,它会在渲染完成后触发。如果您将其视为基于 class 的组件,则等同于 componentDidMount 方法。
  • useEffect 中返回的函数在组件从 UI 中移除或即将重新渲染(以避免内存泄漏)之前被调用。在执行下一个效果之前,始终会清除上一个效果。它保证在任何新渲染之前 运行。等价于 componentWillUnmount.

示例

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

  • 安装组件后,效果主体内的代码将 运行;
  • 清理功能保持不变,准备好在组件重新呈现/从屏幕上移除之前运行。

现在让我们假设有什么触发了重新渲染。由于它被列为 useEffect 依赖的东西,效果将重新执行如下:

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

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

考虑一些具有以下内容的简单组件

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

假设传递的 props 发生了变化,您可能认为它是这样的

  1. 'cleaning up'
  2. 新道具
  3. 'rendering...'
  4. 'Effect is applied'

然而,实际发生了以下情况

  1. 新道具
  2. 'rendering...'
  3. 'cleaning up'
  4. 'Effect is applied'

也就是说,清理函数运行 AFTER 新的 render/painting 但 BEFORE 'new' 效果已应用,docs 对此

可能有点模棱两可

the previous effect is cleaned up before executing the next effect

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

根据反应文档,

Cleaning up an effect

The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect.

Timing of effects

React will always flush a previous render’s effects before starting a new update.

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