v17 的生命周期钩子函数概览
类组件
挂载时顺序
- constructor()
- static getDerivedStateFromProps(props, state)
- render()
- componentDidMount()
更新时顺序
- static getDerivedStateFromProps(props, state)
- shouldComponentUpdate()
- render()
- static getSnapshotBeforeUpdate(prevProps, prevState)
- componentDidUpdate()
卸载
- componentWillUnmount()
函数式组件
// 第一次渲染之后和每次更新之后都会执行,相当于类组件的componentDidMount 和 componentDidUpdate
useEffect(() => {
document.title = `You clicked ${count} times`;
// 卸载时调用,相当于类组件的componentWillUnmount
return ()=> {}
// 数组表示更新依赖的属性
}, []);
现版本废弃的生命周期钩子函数
v15 和 v16之后版本的生命周期对比- componentWillMount
- componentWillUpdate
- componentWillReceiveProps
共同点
都处于 render 阶段
废弃原因
React 团队出于性能的考虑,在v16时引入了Fiber架构,这里简要概括一下。
Fiber架构下, react渲染程序会将一个大的更新任务拆解为许多个小任务。每当执行完一个小任务时,渲染线程都会把主线程交回去,看看有没有优先级更高的工作要处理,确保不会出现其他任务被“饿死”的情况,进而避免同步渲染带来的卡顿。在这个过程中,渲染线程不再“一去不回头”,而是可以被打断的,这就是所谓的“异步渲染”。
在 Fiber 机制下,render 阶段是允许暂停、终止和重启的。
废弃的生命周期钩子函数,它们都处于render阶段,都可能被重复执行。
使用废弃的生命周期钩子函数可能造成的问题
-
完全可以转移到 componentDid(xxx) 中去做
以前以为,在 willMount 里发异步请求,能让数据得到的快些。但是,componentWillMount 结束后,render 会迅速地被触发,所以说首次渲染依然会在数据返回之前执行。这样做不仅没有达到你预想的目的,还会导致服务端渲染场景下的冗余请求等额外问题,得不偿失。 -
在 Fiber 带来的异步渲染机制下,可能会导致非常严重的 Bug
假如你在 componentWillxxx 里发起了一个付款请求。由于 render 阶段里的生命周期都可以重复执行,在 componentWillxxx 被打断 + 重启多次后,就会发出多个付款请求。
或者你可能会习惯在 componentWillReceiveProps(在已挂载的组件接收新的 props 之前被调用) 里操作 DOM(比如说删除符合某个特征的元素),那么 componentWillReceiveProps 若是执行了两次,你可能就会一口气删掉两个符合该特征的元素。 - 在 componentWillReceiveProps 和 componentWillUpdate 里滥用 setState 导致重复渲染死循环的
网友评论