react新旧生命周期区别
①旧生命周期删除三个钩子:componentWillMount、componentWillUpdate、componentWillReceiveProps这三个钩子在17.版本使用时要加上前缀UNSAFE_,即UNSAFE_componentWillMoun否则会有警告甚至报错。增加使用成本,减少程序员使用。这是因为这些生命周期方法经常被误解和滥用,UNSAFE_不是指不安全,而是在未来版本中(maybe 18.)可能出现bug,特别是异步渲染中。实际很少使用这三个钩子,基本不用的。
②新生命周期增加钩子:getDerivedStateFromProps、getSnapshotBeforeUpdate
总结:
新生命周期图解:
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
1. constructor()
2. getDerivedStateFromProps
3. render()
4. componentDidMount() =====> 常用一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1. getDerivedStateFromProps
2. shouldComponentUpdate()
3. render()
4. getSnapshotBeforeUpdate
5. componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1. componentWillUnmount() =====> 常用 一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
新的生命周期钩子: static getDerivedStateFromProps
React 在实例化组件之后以及重新渲染组件之前,将调用新的静态 getDerivedStateFromProps 生命周期方法。该方法类似于 componentWillReceiveProps,可以用来控制 props 更新 state 的过程。它返回一个对象表示新的 state。如果不需要更新组件,返回 null 即可。
getDerivedStateFromProps 与 componentDidUpdate一起将会替换掉所有的 componentWillReceiveProps。
代码:
<script type="text/babel"> //创建组件 class Count extends React.Component { constructor(props) { console.log('Count---constructor'); super(props) //初始化状态 this.state = { count: 0 } } //加1按钮的回调 add = () => { //获取原状态 const { count } = this.state //更新状态 this.setState({ count: count + 1 }) } //卸载组件按钮的回调 death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } //强制更新按钮的回调 force = () => { this.forceUpdate() } //若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps static getDerivedStateFromProps(props, state) { console.log('getDerivedStateFromProps', props, state); return null } //在更新之前获取快照 getSnapshotBeforeUpdate() { console.log('getSnapshotBeforeUpdate'); return 'atguigu' } //组件挂载完毕的钩子 componentDidMount() { console.log('Count---componentDidMount'); } //组件将要卸载的钩子 componentWillUnmount() { console.log('Count---componentWillUnmount'); } //控制组件更新的“阀门” shouldComponentUpdate() { console.log('Count---shouldComponentUpdate'); return true } //组件更新完毕的钩子 componentDidUpdate(preProps, preState, snapshotValue) { console.log('Count---componentDidUpdate', preProps, preState, snapshotValue); } render() { console.log('Count---render'); const { count } = this.state return ( <div> <h2>当前求和为:{count}</h2> <button onClick={this.add}>点我+1</button> <button onClick={this.death}>卸载组件</button> <button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button> </div> ) } } //渲染组件 ReactDOM.render(<Count count={199} />, document.getElementById('test')) </script>
新的生命周期钩子: getSnapshotBeforeUpdate
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
。
class Example extends React.Component {
getSnapshotBeforeUpdate(prevProps, prevState) {
// ...
}
}
getSnapshotBeforeUpdate 方法在 React 对视图做出实际改动(如 DOM 更新)发生前被调用,
这个函数接收两个参数 分别是更新前面的props和更新前的state
返回值将作为 componentDidUpdate 的第三个参数:
(可以在getSnapshotBeforeUpdate返回更新前的必要的参数,比如dom更新前滚轮的位置之类的,然后在componentDidUpdate 中对dom做一些操作,因为componentDidUpdate 执行完以后dom就更新完毕了)
//组件更新完毕的钩子
componentDidUpdate(preProps, preState, snapshotValue) {
console.log('Count---componentDidUpdate', preProps, preState, snapshotValue);
}
代码:
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// 我们是否在 list 中添加新的 items ?
// 捕获滚动位置以便我们稍后调整滚动位置。
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
// 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
//(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}
参考链接:
尚硅谷2021版React技术全家桶全套完整版(零基础入门到精通/男神天禹老师亲授)_哔哩哔哩_bilibili
react16.8 新的生命周期getDerivedStateFromProps和 getSnapshotBeforeUpdate 用法 - 程序員劝退师 - 博客园