使用 React useEffect 钩子卸载

如何使用 useEffect钩子(或任何其他钩子)来复制 componentWillUnmount

在传统的 class 组件中,我会这样做:

class Effect extends React.PureComponent {
componentDidMount() { console.log("MOUNT", this.props); }
componentWillUnmount() { console.log("UNMOUNT", this.props); }
render() { return null; }
}

useEffect挂钩:

function Effect(props) {
React.useEffect(() => {
console.log("MOUNT", props);


return () => console.log("UNMOUNT", props)
}, []);


return null;
}

(完整例子: https://codesandbox.io/s/2oo7zqzx1n)

这是不工作的,因为“清理”函数返回在 useEffect捕获道具,因为他们在挂载期间,而不是状态的道具在卸载。

我怎样才能得到最新版本的道具在 useEffect清理 没有运行的功能体(或清理)对每个道具的变化?

类似的 有个问题没有解决访问最新道具的问题。

反应文件州:

如果您想运行一个效果并且只清除一次(在挂载和卸载时) ,那么可以传递一个空数组([])作为第二个参数。这告诉 React,您的效果不依赖于任何来自道具或状态的值,因此它永远不需要重新运行。

不过在这种情况下,我依靠的道具... ... 但只有清理的一部分..。

104924 次浏览

You can make use of useRef and store the props to be used within a closure such as 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>;
}

DEMO

However a better way is to pass on the second argument to useEffect so that the cleanup and initialisation happens on any change of desired props

React.useEffect(() => {
return () => {
console.log(props.current);
};
}, [props.current]);

useLayoutEffect() is your answer in 2021

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

This is equivalent to ComponentWillUnmount.

99% of the time you want to use useEffect, but if you want to perform any actions before unmounting the DOM then you can use the code I provided.

useEffect(() => {
if (elements) {
const cardNumberElement =
elements.getElement('cardNumber') ||  // check if we already created an element
elements.create('cardNumber', defaultInputStyles); // create if we did not
            

cardNumberElement.mount('#numberInput');
}
}, [elements]);

useLayoutEffect is great for cleaning eventListeners on DOM nodes.

Otherwise, with regular useEffect ref.current will be null on time hook triggered

More on react docs https://reactjs.org/docs/hooks-reference.html#uselayouteffect

  import React, { useLayoutEffect, useRef } from 'react';


const audioRef = useRef(null);




useLayoutEffect(() => {
if (!audioRef.current) return;


const progressEvent = (e) => {
setProgress(audioRef.current.currentTime);
};


audioRef.current.addEventListener('timeupdate', progressEvent);


return () => {
try {
audioRef.current.removeEventListener('timeupdate', progressEvent);
} catch (e) {
console.warn('could not removeEventListener on timeupdate');
}
};
}, [audioRef.current]);






Attach ref to component DOM node

<audio ref={audioRef} />