我们如何使用react钩子实现componentWillUnmount?

Geo*_*sov 9 javascript reactjs react-hooks

卸载和销毁组件之前componentWillUnmount()立即调用该方法。如果我们使用空数组([])作为第二个参数,并将函数放入return语句中,则它将在组件卸载后甚至在另一个组件安装后执行。据我所知,这样做是出于性能原因。为了不延迟渲染。useEffect

因此,问题是-如何在挂载组件之前使用钩子调用某些函数?

我正在尝试做的是一个应用程序,该应用程序可以在用户键入时保存用户的输入(无需提交表单)。我使用setInterval每N秒保存一次更新的文本。而且我需要在组件卸载之前强制保存更新。我不想在导航之前使用React Router的提示。这是电子应用。感谢您对实现此类功能的任何想法或建议。

更新资料

不幸的是,让浏览器绘制后,“ 带有清理的效果”才能运行。可以在这里找到更多详细信息:那么清理呢?。基本上,这意味着清除操作是在卸载组件后运行的,它与中执行代码不同componentWillUnmount()。如果将console.log语句放入清理代码和其他组件中,则可以清楚地看到调用的顺序。问题是我们是否可以使用钩子卸载组件之前执行一些代码。

更新2

如我所见,我应该更好地描述我的用例。让我们想象一个理论上的应用程序,它将其数据保存在Redux存储中。而且我们有两个具有某种形式的组件。为简单起见,我们没有任何后端或任何异步逻辑。我们仅将Redux存储用作数据存储。

我们不想在每次击键时都更新Redux存储。因此,我们将实际值保持在本地组件的状态中,当组件安装时,将使用商店中的值进行初始化。我们还创建一个效果,将setInterval设置为1s。

我们有以下过程。用户键入一些内容。更新将以本地组件状态存储,直到调用我们的setInterval回调。回调只是将数据放入存储中(调度动作)。我们将回调放在useEffect返回语句中,以在卸载组件时强制保存存储,因为在这种情况下我们希望尽快保存数据进行存储。

当用户在第一个组件中键入内容并立即进入第二个组件(快于1s)时,就会出现问题。由于在重新渲染后将调用第一个组件中的清理,因此在安装第二个组件之前不会更新我们的商店。因此,第二个组件将获得过时的值到其本地状态。

如果我们放入回调,componentWillUnmount()它将在卸载之前被调用,并且存储将在下一个组件安装之前被更新。那么我们可以使用钩子来实现它吗?

小智 14

自从引入了钩子之后useLayoutEffect,你现在可以做

useLayoutEffect(() => () => {
  // Your code here.
}, [])
Run Code Online (Sandbox Code Playgroud)

模拟componentWillUnmount。它在卸载期间运行,但在元素实际离开页面之前运行。

  • 这也解决了我的一个类似问题:我在 useEffect 中的组件的一个子组件上添加了一个 eventListener,但是在 useEffect 返回回调中,子组件已经被卸载并从 DOM 中删除 -> 我无法再在其上删除 EventListener。使用 useLayoutEffect 解决了这个问题,非常感谢。 (2认同)

the*_*man 9

componentWillUnmount可以通过在useEffect钩子内部返回一个函数来模拟。返回的函数将在每次重新呈现组件之前被调用。严格来说,这是同一件事,但是您应该能够模拟您想要使用此行为的任何行为。

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
})
Run Code Online (Sandbox Code Playgroud)

在此处查看有关同一问题的更详细的说明。

  • 虽然这显然解决了一些人的问题,但它并没有回答问题。钩子上的返回函数在卸载之后运行,如何在卸载之前运行带有钩子的代码? (4认同)
  • 似乎大多数人都在想这件事。但是实际上,返回的函数在重新渲染之前不会被调用。重新渲染后调用它。 (2认同)
  • 如果我使用空数组,如果我想读取一个状态但它一直抱怨我应该将其添加到依赖项数组中,我该怎么办? (2认同)

Sim*_*n L 6

我同意 Frank 的观点,但代码需要如下所示,否则它将仅在第一次渲染时运行:

useLayoutEffect(() => {
    return () => {
        // Your code here.
    }
}, [])
Run Code Online (Sandbox Code Playgroud)

这相当于 ComponentWillUnmount


Dav*_*haw 5

这里的问题是如何在卸载之前使用钩子运行代码?带有钩子的返回函数在卸载后运行,虽然这对大多数用例没有影响,但它们在某些地方却是一个关键的区别。

对此进行了一些调查后,我得出的结论是,目前 hooks 根本没有提供componentWillUnmount. 所以如果你有一个需要它的用例,至少对我来说主要是,非 React 库的集成,你只需要按照旧的方式来做,并使用一个组件。

更新:请参阅下面的答案UseLayoutEffect(),看起来现在解决了这个问题。