Javascript 我们如何使用react钩子实现componentWillUnmount?
方法Javascript 我们如何使用react钩子实现componentWillUnmount?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,方法componentWillUnmount()在卸载和销毁组件之前立即调用。如果我们使用带有空数组([])的useffect作为第二个参数,并将函数放在return语句中,那么它将在卸载组件后执行,甚至在装载另一个组件后也会执行。据我所知,这样做是出于性能原因。为了不延迟渲染 所以问题是-在卸载组件之前,我们如何使用钩子调用某个函数 我试图做的是一个应用程序,它在用户输入时保存用户的输入(不提交表单)。我使用setInterval每N秒保存一次更新的文本。我需要在卸载组件之前强制保存更新。我不
componentWillUnmount()
在卸载和销毁组件之前立即调用。如果我们使用带有空数组([])的useffect
作为第二个参数,并将函数放在return语句中,那么它将在卸载组件后执行,甚至在装载另一个组件后也会执行。据我所知,这样做是出于性能原因。为了不延迟渲染
所以问题是-在卸载组件之前,我们如何使用钩子调用某个函数
我试图做的是一个应用程序,它在用户输入时保存用户的输入(不提交表单)。我使用setInterval每N秒保存一次更新的文本。我需要在卸载组件之前强制保存更新。我不想在导航前使用react路由器的提示。这是一个电子应用程序。对于如何实现这些功能,我非常感谢您的任何想法或建议
更新
不幸的是,让浏览器绘制后运行。可在此处找到更多详细信息:。它基本上意味着在卸载组件后运行清理,这与在componentWillUnmount()
中执行代码不同。如果将console.log语句放入清理代码和其他组件中,我可以清楚地看到调用的顺序。问题是我们是否可以在使用钩子卸载组件之前执行一些代码
更新2
如我所见,我应该更好地描述我的用例。让我们想象一个理论应用程序,它将数据保存在Redux存储中。我们有两个部分,有一些形式。为简单起见,我们没有任何后端或任何异步逻辑。我们只使用Redux存储作为数据存储
我们不想在每次击键时都更新Redux存储。因此,我们将实际值保留在本地组件的状态中,当组件挂载时,我们使用存储中的值初始化该状态。我们还创建了一个效果,设置了1s的设置间隔
我们有以下过程。用户输入一些东西。在调用setInterval回调之前,更新存储在本地组件状态。回调只是将数据放入存储(分派操作)。我们将回调放在useffect return语句中,以便在卸载组件时强制保存到存储,因为我们希望在这种情况下尽快将数据保存到存储
当用户在第一个组件中键入某些内容并立即转到第二个组件(快于1s)时,就会出现问题。由于第一个组件中的清理将在重新渲染后调用,因此在第二个组件装入之前不会更新存储。因此,第二个组件将向其本地状态获取过时的值
如果我们将回调放入
componentWillUnmount()
中,它将在卸载之前被调用,并且存储将在下一个组件装载之前更新。那么我们可以使用钩子来实现吗?组件将卸载可以通过在useffect
钩子中返回一个函数来模拟。返回的函数将在每次重新提交组件之前调用。严格地说,这是同一件事,但你应该能够模拟任何行为,你想要使用它
useEffect(() => {
const unsubscribe = api.createSubscription()
return () => unsubscribe()
})
更新
每次重新加载时,上述操作都将运行。但是,仅模拟装载和卸载时的行为(即componentDidMount和componentWillUnmount)。useEffect接受一个需要为空数组的数组
useEffect(() => {
const unsubscribe = api.createSubscription()
return () => unsubscribe()
}, [])
请参阅同一问题的更详细解释。在卸载组件之前还是之后调用useffect
返回的函数并不重要:您仍然可以通过闭包访问states valuey:
const [input, setInput] = useState(() => Store.retrieveInput());
useEffect(() => {
return () => Store.storeInput(input); // < you can access "input" here, even if the component unmounted already
}, []);
const[input,setInput]=useState(()=>Store.retrieveInput());
useffect(()=>{
return()=>Store.storeInput(input);//<
}, []);
如果不在组件状态下管理输入,则整个结构将被破坏,应该在正确的位置更改为管理状态。在您的情况下,您应该将组件的共享输入状态提升到父级。钩子上的JS文档指定:
效果还可以选择指定如何通过
返回一个函数
因此,您在useffect
hook中返回的任何函数都将在组件卸载时执行,以及在由于后续渲染而重新运行效果之前执行。这里的问题是,在卸载之前如何使用hook运行代码?带有钩子的返回函数在卸载后运行,虽然这对大多数用例没有影响,但在某些情况下,它们是一个关键区别
在对此做了一点调查之后,我得出结论,当前的钩子并不能直接替代组件willunmount
。因此,如果您有一个需要它的用例,至少对我来说主要是非反应libs的集成,那么您只需使用旧的方法并使用一个组件即可
希望这在将来会有所改变经过一点研究,发现-你仍然可以做到这一点。有点棘手,但应该可以
您可以使用useRef并存储要在闭包(例如render useEffect return callback method)中使用的道具
function Home(props) {
const val = React.useRef();
React.useEffect(
() => {
val.current = props;
},
[props]
);
React.useEffect(() => {
return () => {
console.log(props, val.current);
};
}, []);
return <div>Home</div>;
}
由于引入了useLayoutEffect
hook,您现在可以
useLayoutEffect(() => () => {
// Your code here.
}, [])
要模拟组件,将卸载。这在卸载期间运行,但在元素实际离开页面之前。我同意Frank的观点,但代码需要如下所示,否则它将仅在第一次呈现时运行:
useLayoutEffect(() => {
return () => {
// Your code here.
}
}, [])
这相当于组件将卸载请阅读。这就是答案。@ArupRaksh
useLayoutEffect(() => {
return () => {
// Your code here.
}
}, [])