在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
在React的官方文档中提到了-
如果你熟悉React类的生命周期方法,你可以思考 将useEffect钩子作为componentDidMount, componentDidUpdate和 componentWillUnmount总和。
我的问题是-我们如何在钩子中使用componentWillMount()生命周期方法?
当前回答
useLayoutEffect可以用一个空的观察者集([])来完成这一点,如果功能实际上类似componentWillMount——它将在第一个内容到达DOM之前运行——尽管实际上有两个更新,但它们在绘制到屏幕之前是同步的。
例如:
function MyComponent({ ...andItsProps }) {
useLayoutEffect(()=> {
console.log('I am about to render!');
},[]);
return (<div>some content</div>);
}
与useState相比,使用初始化器/setter或useEffect的好处是,尽管它可以计算一个渲染传递,但用户不会注意到DOM的实际重新渲染,并且它是在第一次明显的渲染之前运行的,而useEffect则不是这样。缺点当然是在你的第一次渲染中有轻微的延迟,因为在绘制到屏幕之前必须进行检查/更新。不过,这确实取决于您的用例。
我个人认为,useMemo在一些特定的情况下是很好的,当你需要做一些沉重的事情时——只要你记住这是例外与规范。
其他回答
根据reactjs.org的说法,componentWillMount在未来将不受支持。 https://reactjs.org/docs/react-component.html#unsafe_componentwillmount
不需要使用componentWillMount。
如果你想在组件挂载之前执行一些操作,只需在构造函数()中执行即可。
如果你想做网络请求,不要在componentWillMount中做。这是因为这样做会导致意想不到的错误。
网络请求可以在componentDidMount中完成。
希望能有所帮助。
2019年8月3日更新
你请求componentWillMount的原因可能是因为你想在呈现之前初始化状态。
就在我们的地盘上做吧。
const helloWorld=()=>{
const [value,setValue]=useState(0) //initialize your state here
return <p>{value}</p>
}
export default helloWorld;
或者你想在componentWillMount中运行一个函数,例如,如果你的原始代码看起来像这样:
componentWillMount(){
console.log('componentWillMount')
}
使用hook,你所需要做的就是删除生命周期方法:
const hookComponent=()=>{
console.log('componentWillMount')
return <p>you have transfered componeWillMount from class component into hook </p>
}
我只是想对第一个关于useEffect的答案补充一些东西。
useEffect(()=>{})
useEffect运行在每次渲染上,它是componentDidUpdate, componentDidMount和ComponentWillUnmount的组合。
useEffect(()=>{},[])
如果我们在useEffect中添加一个空数组,它只在组件挂载时运行。这是因为useEffect将比较您传递给它的数组。 所以它不一定是空数组。它可以是一个不变的数组。例如,它可以是[1,2,3]或['1,2']。useEffect仍然只在组件挂载时运行。
这取决于你是想让它只运行一次,还是在每次渲染后运行。如果您忘记添加数组,只要您知道自己在做什么,这并不危险。
我为hook创建了一个示例。请查看一下。
https://codesandbox.io/s/kw6xj153wr
2019年8月21日更新
我写上面的答案已经有一段时间了。有件事我觉得你需要注意。 当你使用
useEffect(()=>{},[])
当react比较传递给数组[]的值时,它使用Object.is()进行比较。 如果您将一个对象传递给它,例如
useEffect(()=>{},[{name:'Tom'}])
这和:
useEffect(()=>{})
每次都会重新呈现,因为object .is()比较对象时比较的是对象的引用,而不是值本身。这和为什么{}==={}返回false是一样的,因为它们的引用不同。 如果你仍然想比较对象本身而不是引用,你可以这样做:
useEffect(()=>{},[JSON.stringify({name:'Tom'})])
2021年7月9日更新:
关于依赖关系的一些更新:
一般来说,如果你使用一个函数或一个对象作为依赖项,它总是会重新呈现。但是react已经为您提供了解决方案:useCallback和useMemo
useCallback能够记住一个函数。 useMemo能够记住一个对象。
请看这篇文章:
https://javascript.plainenglish.io/5-useeffect-infinite-loop-patterns-2dc9d45a253f
钩子中的React生命周期方法
为了简单的视觉参考,请遵循此图像
正如您在上图中所看到的,对于ComponentWillUnmount,您必须这样做
useEffect(() => {
return () => {
console.log('componentWillUnmount');
};
}, []);
这可能不是componentWillMount方法的确切替代方法,但这里有一个方法可以用来实现同样的目标,但要使用useEffect:
首先初始化检索数据的对象为空值,并定义useEffect方法:
const [details, setDetails] = useState("")
useEffect(() => {
retrieveData();
}, []);
const retrieveData = () => {
getData() // get data from the server
.then(response => {
console.log(response.data);
setDetails(response.data)
})
.catch(e => {
console.log(e);
})
}
在JSX中,我们返回一个三元操作符
*return(
<div>
{
details ? (
<div class="">
<p>add Your Jsx Here</p>
</div>
): (
<div>
<h4>Content is still Loading.....</h4>
</div>
)
}
</div>
)*
这将确保在对象'details'中有数据之前,terenary操作符的第二部分会被加载,该操作符会触发useEffect方法,该方法导致在'details'对象中设置从服务器接收到的数据,从而呈现主JSX
你不能在钩子中使用任何现有的生命周期方法(componentDidMount, componentDidUpdate, componentWillUnmount等)。它们只能在类组件中使用。而Hooks只能用于功能组件。下面这句话来自React文档:
如果你熟悉React类的生命周期方法,你可以把useEffect Hook看作componentDidMount、componentDidUpdate和componentWillUnmount的组合。
建议是,可以在功能组件中从类组件中模拟这些生命周期方法。
componentDidMount中的代码在组件挂载时运行一次。useEffect钩子等价于此行为是
useEffect(() => {
// Your code here
}, []);
注意这里的第二个参数(空数组)。这将只运行一次。
如果没有第二个参数,useEffect钩子将在组件的每次渲染时被调用,这可能是危险的。
useEffect(() => {
// Your code here
});
componentWillUnmount用于清理(比如删除事件监听器,取消定时器等)。假设您正在componentDidMount中添加一个事件侦听器,并在componentWillUnmount中删除它,如下所示。
componentDidMount() {
window.addEventListener('mousemove', () => {})
}
componentWillUnmount() {
window.removeEventListener('mousemove', () => {})
}
与上述代码等价的钩子如下所示
useEffect(() => {
window.addEventListener('mousemove', () => {});
// returned function will be called on component unmount
return () => {
window.removeEventListener('mousemove', () => {})
}
}, [])
有一个很好的解决方案来实现componentDidMount和componentWillUnmount与useEffect。
根据文档,useEffect可以返回一个“清理”函数。该函数不会在第一次useEffect调用时调用,只在后续调用时调用。
因此,如果我们使用useEffect钩子而没有任何依赖关系,那么该钩子只会在组件挂载时被调用,而“cleanup”函数则会在组件卸载时被调用。
useEffect(() => {
console.log('componentDidMount');
return () => {
console.log('componentWillUnmount');
};
}, []);
只有在卸载组件时才调用清理返回函数调用。
希望这能有所帮助。