在React 17版本中对生命周期函数的调整
-
这三个钩子函数可能会被废弃
componentWillMount
componentWillUpdate
componentWillReceiveProps
如果直接使用会报警告。在使用的时候在函数前面加上UNSAFE_可以避免警告。废弃原因:过时的组件生命周期往往会带来不安全的编码实践。这些生命周期方法经常被误解和滥用;此外,我们预计, 在异步渲染中,它们潜在的误用问题可能更大。我们将在即将发布的版本中为这些生命周期添加 “UNSAFE_” 前缀。 (这里的 “unsafe” 不是指安全性,而是表示使用这些生命周期的代码在 React 的未来版本中更有可能出现 bug, 尤其是在启用异步渲染之后。) -
react 17版本另外新加了两个新的钩子函数:
1). static getDerivedStateFromProps(): 挂载和更新时候都会触发
2). static getSnapshotBeforeUpdate(): 更新时候才会触发
新的生命周期
一、getDerivedStateFromProps
这个钩子函数会将props中接收到的参数,自动合并到当前组件state中。
由于合并的状态是从props中获取的数据,所以合并后的状态也称为派生状态
使用时应注意以下几点:
- 使用时候必须使用static
- 必须返回一个返回值,可以是一个值 也可以 是null
- 这个方法使用比较罕见,除非state的值在任何时候都取决于props才会使用这个钩子函数,因此这个钩子函数也不常用。
- getDerivedStateFromProps合并后的派生状态,会使代码冗余,难以维护
- 组件挂载和更新时候都会触发这个钩子函数
二、getSnapshotBeforeUpdate
可以在组件更新之前做⼀些事情, ⼀些特殊案例会使⽤到。
此生命周期的返回值将作为第三个参数传递给 componentDidUpdate(通常不需要,但在重新渲染过程中手动保留滚动位置等情况下非常有用。
getSnapshotBeforeUpdate的使用案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>03_getSnapshotBeforeUpdate</title>
<style>
.list{
width: 200px;
height: 100px;
background-color: #61dafb;
overflow: auto;
}
/**
var list = document.getElementsByClassName('list')[0]
1.list.scrollTop可以获取或者设置第0位距离顶部的高度
2.list.scrollHeight可以获取可滚动区域的高度
*/
</style>
</head>
<body>
<div id="test"></div>
<script src="https://cdn.staticfile.org/react/17.0.1/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/17.0.1/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script type="text/babel">
class NewsList extends React.Component {
/**
* 需求:新闻在不断地新增,需要保持当前滚动条的位置,不发生改变
* 解决方案:现在的滚动条高度=新的滚动条高度-旧的滚动条高度
* @type {{newsList: Array}}
*/
state = {newsList: []}
//组件挂载之后更新数据
componentDidMount(){
setInterval(()=>{
let {newsList} = this.state
let news = '新闻' + (newsList.length + 1);
this.setState({newsList: [news, ...newsList]})
}, 1000)
}
getSnapshotBeforeUpdate(preProps, preState){
// 组件更新之前的高度
let oldHeight = this.refs.list.scrollHeight
return {oldHeight}
}
componentDidUpdate(preProps, preState, snapshot){
//组件更新之后的高度
let newHeight = this.refs.list.scrollHeight
// scrollTop 需要改变的值
let finalHeight = newHeight - snapshot.oldHeight
console.log('finalHeight', finalHeight)
// 设置滚动条高度
this.refs.list.scrollTop += finalHeight
}
render() {
const {newsList} = this.state
return (
<div className="list" ref='list'>
{
newsList.map((item, index)=>{
return<div key={index}>{item}</div>
})
}
</div>
);
}
}
ReactDOM.render(<NewsList count={100}/>, document.getElementById('test'))
</script>
</body>
</html>
总结
- 初始化阶段: 由ReactDOM.render()触发---初次渲染
- constructor()
- getDerivedStateFromProps()
- render()
- componentDidMount()
- 更新阶段: 由组件内部this.setSate()或父组件render触发
- getDerivedStateFromProps
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
- 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount() 重要的钩子:
- render:初始化渲染或更新渲染调⽤
- componentDidMount:开启监听, 发送ajax请求
- componentWillUnmount:做⼀些收尾⼯作, 如: 清理定时器
即将废弃的勾⼦
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate 现在使⽤会出现警告,下⼀个⼤版本需要加上UNSAFE_前缀才能使⽤,以后可能会被彻底废弃,不建议使⽤。