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

IT技术 javascript reactjs react-hooks
2021-05-05 17:13:41

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

所以问题是 - 我们如何在卸载组件之前使用钩子调用某些函数?

我想要做的是一个应用程序,它在用户输入时保存他的输入(不提交表单)。我使用 setInterval 每 N 秒保存更新的文本。我需要在卸载组件之前强制保存更新。我不想在导航之前通过react-router使用提示。这是一个电子应用程序。我感谢有关如何实现此类功能的任何想法或建议。

更新

不幸的是,Effects with Cleanup在让浏览器绘制后运行。更多细节可以在这里找到:那么清理呢?. 它基本上意味着在卸载组件后运行清理,这与执行componentWillUnmount(). 如果我将 console.log 语句放在清理代码和另一个组件中,我可以清楚地看到调用顺序。问题是我们是否可以使用钩子卸载组件之前执行一些代码

更新2

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

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

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

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

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

4个回答

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

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
})

更新

每次重新渲染时都会运行上述内容。但是,仅模拟安装和卸载时的行为(即 componentDidMount 和 componentWillUnmount)。useEffect 需要第二个参数,它需要是一个空数组。

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
}, [])

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

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

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

更新:请参阅下面的答案,UseLayoutEffect()它似乎可以解决此问题。

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

useLayoutEffect(() => () => {
  // Your code here.
}, [])

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

我同意 Frank,但代码需要如下所示,否则它只会在第一次渲染时运行:

useLayoutEffect(() => {
    return () => {
        // Your code here.
    }
}, [])

这相当于 ComponentWillUnmount