react生命周期笔记
1. 旧版生命周期
- constructor:构造器
- componentWillMount:组件将要挂载的钩子
- render:初始化渲染或更新渲染调用
- componentDidMount:组件挂载完成的钩子
- componentWillUnmount:组件将要卸载的钩子
- componentWillReceiveProps:
- shouldComponentUpdate:组件状态将要更新的钩子
返回值:true-更新,false-不更新(如果不写,react默认为true,为false底下的所以钩子都不会执行)
- componentWillUpdate:组件将要更新的钩子
- componentDidUpdate:组件更新完成的钩子
// 挂载组件
ReactDOM.render(<MyCompontent />, document.querySelector('#app'))
// 卸载组件
ReactDOM.unmountComponentAtNode(document.querySelector('#app'))
下面是具体使用:
class MyCompontent extends React.Component {
// 构造器
constructor(props) {
console.log('constructor')
super(props)
// 初始化状态
this.state = {
count: 0
}
}
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.querySelector('#app'))
}
// 组件将要挂载的钩子
componentWillMount() {
console.log('componentWillMount')
}
// 组件挂载完成的钩子
componentDidMount() {
console.log('componentDidMount')
}
// 组件将要卸载的钩子
componentWillUnmount() {
console.log('componentWillUnmount')
}
// 渲染
render() {
console.log('render')
return (
<div>
<button onClick={ this.death }>卸载组件</button>
</div>
)
}
}
ReactDOM.render(<MyCompontent />, document.querySelector('#app'))
控制台打印的结果:
在数据更新时有其他的生命周期:
路线2:setState()
class MyCompontent extends React.Component {
// 构造器
constructor(props) {
console.log('constructor')
super(props)
// 初始化状态
this.state = {
count: 0
}
}
add = () => {
this.setState({
count: this.state.count + 1
})
}
death = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.querySelector('#app'))
}
// 组件将要挂载的钩子
componentWillMount() {
console.log('componentWillMount')
}
// 组件挂载完成的钩子
componentDidMount() {
console.log('componentDidMount')
}
// 组件将要卸载的钩子
componentWillUnmount() {
console.log('componentWillUnmount')
}
// 组件将要接受新的属性的钩子
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps')
}
// 组件状态将要更新的钩子
// 返回值:true-更新,false-不更新(如果不写,react默认为true,为false底下的所以钩子都不会执行)
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate')
return true
}
// 组件将要更新的钩子
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate')
}
// 渲染
render() {
console.log('render')
const { count } = this.state
return (
<div>
<h1>当前求和为:{ count }</h1>
<button onClick={ this.add }>点击+1</button>
<button onClick={ this.death }>卸载组件</button>
</div>
)
}
}
ReactDOM.render(<MyCompontent />, document.querySelector('#app'))
当点击按钮+1时候,控制台会输出下面内容:
⚠️注意:但如果shouldComponentUpdate
这个钩子的返回值为false旧不会进行下面的其他生命周期,类似于“阀门”一样
线路3:forceUpdate()
强制更新
强制更新会绕过shouldComponentUpdate
这个过程,进行页面更新
class MyCompontent extends React.Component {
// 构造器
constructor(props) {
console.log('constructor')
super(props)
// 初始化状态
this.state = {
count: 0
}
}
force = () => {
this.forceUpdate()
}
// 组件状态将要更新的钩子
// 返回值:true-更新,false-不更新(如果不写,react默认为true,为false底下的所以钩子都不会执行)
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate')
return false
}
// 组件将要更新的钩子
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate')
}
// 组件更新完成的钩子
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate')
}
// 渲染
render() {
console.log('render')
const { count } = this.state
return (
<div>
<h1>当前求和为:{ count }</h1>
<button onClick={ this.force }>强制更新</button>
</div>
)
}
}
ReactDOM.render(<MyCompontent />, document.querySelector('#app'))
即使shouldComponentUpdate
为false,在force
方法中this.forceUpdate()
的会强制更新页面,控制台打印结果如下:
线路1:父子组件
其余钩子触发与线路2相同
class Father extends React.Component {
state = {
carName: '奔驰'
}
changeCar = () => {
this.setState({
carName: '宝马'
})
}
render() {
return (
<div>
<p>我是父组件</p>
<button onClick={this.changeCar}>点击换车</button>
<hr />
<Son carName={this.state.carName} />
</div>
)
}
}
class Son extends React.Component {
// 组件将要接收新的props的钩子(第一次不算,需要props发生变化才会触发)
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps')
console.log('父组件传过来的车是:', nextProps)
}
render() {
return (
<div>
<p>我是子组件</p>
<p>父组件传来的车是:{this.props.carName}</p>
</div>
)
}
}
ReactDOM.render(<Father />, document.querySelector('#app'))
点击父组件按钮后,控制台打印结果为:
总结:
- 初始化阶段:由
ReactDOM.render()
触发(初次渲染)- constructor()
- componentWillMount()
- render()
- componentDidMount() 常用,一般在这个钩子中做一些初始化的工作,例如:开启定时器,发送请求,订阅消息,类似于vue中的
mounted
- 更新阶段:由组件内部
this.setState()
或父组件重新render
触发- shouldComponentUpdate() (强制更新不触发)
- componentWillUpdate()
- render()
- componentDidUpdate()
- 卸载组件:由
ReactDOM.unmountComponentAtNode()
触发- componentWillUnmount() 常用,一般在这个钩子中做一些收尾的事
2. 新版生命周期
区别:废弃了3个钩子,新增了两个钩子
1. 废弃:
有三个钩子改名了:(都加上UNSAFE_
这个前缀),原来的这个三个被废弃了
- componentWillMount => UNSAFE_componentWillMount
- componentWillReceiveProps => UNSAFE_componentWillReceiveProps
- componentWillUpdate => UNSAFE_componentWillUpdate
如何记忆:带有will的生命周期钩子,前面都要加
UNSAFE_
,除了componentWillUnmount
这个最重要的不变
2. 新增:
- getDerivedStateFromProps:(用的很少)
该钩子前面要加上static
关键字,会有两个参数:参数1是组件传递的props,参数2是state的值(当state的值在任何时候都取决于props时候会用到这个钩子)
class MyCompontent extends React.Component {
state = {
count: 0
}
add = () => {
this.setState({
count: this.state.count + 1
})
}
static getDerivedStateFromProps(props, state) {
console.log(props, state);
console.log('getDerivedStateFromProps')
// 返回一个状态(state)或null
return null
// return props
}
render() {
console.log('render')
const { count } = this.state
return (
<div>
<h1>当前求和为:{ count }</h1>
<button onClick={ this.add }>点击+1</button>
</div>
)
}
}
ReactDOM.render(<MyCompontent count={199} />, document.querySelector('#app'))
- 当
return props
点击按钮后,控制台输出的结果为:count值被冻结(因为该状态横跨挂载和更新)
- 当
return null
或return state
点击按钮后,count会正常+1
- getSnapshotBeforeUpdate:在更新之前获取快照,处于更新时
render
和componentDidUpdate
之间
数据更新前调用该钩子,返回一个快照值,返回的任何值会作为参数传递给componentDidUpdate
class MyCompontent extends React.Component {
state = {
count: 0
}
add = () => {
this.setState({
count: this.state.count + 1
})
}
// 返回一个快照值,返回的任何值会作为参数传递给componentDidUpdate
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate', prevProps, prevState)
return prevState.count
// return 100 如果返回100,那么componentDidUpdate的snapshot参数就一直是00
}
componentDidUpdate(prevProps, prevState, snapshot) {
// prevProps 之前传递的props值
// prevState 更新前的state值
// snapshot 更新前的getSnapshotBeforeUpdate返回值
console.log('componentDidUpdate', prevProps, prevState, snapshot)
}
render() {
const { count } = this.state
console.log('render')
return (
<div>
<h1>当前求和为:{ count }</h1>
<button onClick={ this.add }>点击+1</button>
</div>
)
}
}
ReactDOM.render(<MyCompontent count={199} />, document.querySelector('#app'))
控制台打印结果如下: