在卸载和销毁组件之前立即调用方法componentWillUnmount()
。如果我们使用带有空数组([])的useEffect
作为第二个参数并将我们的函数放在return语句中,它将在卸载组件后执行,甚至在安装另一个组件之后执行。据我所知,这是出于性能原因而完成的。为了不延迟渲染。
所以问题是 - 如何在卸载组件之前使用钩子调用某些函数?
我想要做的是一个应用程序,在他输入时保存用户的输入(不提交表单)。我每隔N秒使用setInterval来保存更新的文本。我需要在组件卸载之前强制保存更新。我不希望在导航之前使用反应路由器提示。这是一个电子申请。我很欣赏有关如何实现此类功能的任何想法或建议。
更新
不幸的是,Effects with Cleanup在浏览器绘制后运行。更多细节可以在这里找到:So What About Cleanup?。它基本上意味着在卸载组件后运行清理,它与在componentWillUnmount()
中执行代码不同。如果我将console.log语句放在清理代码和另一个组件中,我可以清楚地看到调用的顺序。问题是我们是否可以在使用钩子卸载组件之前执行某些代码。
UPDATE2
我可以看到我应该更好地描述我的用例。让我们设想一个理论应用程序,它将数据保存在Redux商店中。我们有两个组件,有一些形式。为简单起见,我们没有任何后端或任何异步逻辑。我们仅使用Redux存储作为数据存储。
我们不想在每次击键时更新Redux商店。因此,我们将实际值保存在本地组件的状态中,当组件安装时,我们使用商店中的值初始化该状态。我们还创建了一个为1s设置setInterval的效果。
我们有以下过程。用户输入内容。更新存储在本地组件状态,直到调用setInterval回调。回调只是将数据放入商店(调度操作)。我们将回调放在useEffect return语句中,以便在组件卸载时强制保存存储,因为我们希望尽快将数据保存到这种情况。
当用户在第一个组件中键入内容并立即转到第二个组件(快于1秒)时,就会出现问题。由于我们的第一个组件中的清理将在重新渲染后调用,因此在安装第二个组件之前不会更新我们的存储。因此,第二个组件将过时的值传递给其本地状态。
如果我们将回调放在componentWillUnmount()
中,它将在卸载之前被调用,并且在下一个组件安装之前将更新存储。那么我们可以使用钩子实现这个吗?
可以通过在componentWillUnmount
钩子内返回一个函数来模拟useEffect
。返回的函数将在每次重新呈现组件之前调用。严格来说,这是相同的事情,但你应该能够使用它来模拟你想要的任何行为。
useEffect(() => {
const unsubscribe = api.createSubscription()
return () => unsubscribe()
})
查看相同问题here的更详细解释。
在卸载组件之前或之后调用useEffect
返回的函数无关紧要:您仍然可以通过闭包访问状态值:
const [input, setInput] = useState(() => Store.retrieveInput());
useEffect(() => {
return () => Store.storeInput(input); // < you can access "input" here, even if the component unmounted already
}, []);
如果您未在组件状态中管理输入,则整个结构将被破坏,应更改为在正确的位置管理状态。在您的情况下,您应该将组件的共享输入状态提升到父级。
钩子上的ReactJS文档指定了这个:
效果还可以选择通过返回函数来指定如何“清理”它们。
因此,您在useEffect
钩子中返回的任何函数都将在组件卸载时执行,并且在由于后续渲染而重新运行效果之前执行。