可以直接拷贝这段代码,然后执行打开控制台查看生命周期的流程。
注意:默认情况下使用了新的生命周期后,老的生命周期不会去执行。会在控制台报警告
//ComponentLifeCycle
import React, { Component } from 'react';
export default class ComponentLifeCycle extends Component {
constructor(props) {
super(props)
this.state = {
title: '默认文本',
flagCount: Number(0),
value: ''
}
//新的ref绑定方法
this.inputRef = React.createRef();
this.textRef = React.createRef();
}
// 组件将要挂载的时候调用
UNSAFE_componentWillMount() {
console.log('componentWillMount:\n只在第一次render之前调用一次')
//对于某些操作比如说在willMount的时候去调接口的话 请将异步逻辑移步到componentDidMount生命周期
//接口请求放在这里和即将到来的异步呈现模式冲突(其中请求可能被多次启动)
//如果在willMount的时候想要把props的某些属性赋值给state状态机 请将此类操作直接在构造函数中进行
setTimeout(() => {
this.setState({
title: 'componentWillMount'
})
}, 1500)
}
// 当props发生变化时执行,初始化render时不执行,
// 在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,
// 旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用
UNSAFE_componentWillReceiveProps(nextProps, props) {
if (nextProps !== this.props) {
setTimeout(() => {
this.setState({
title: 'componentWillReceiveProps'
})
console.log('componentWillReceiveProps:', '\n新的props', nextProps, '\n老的props', props)
}, 1500)
}
}
// 组件将要跟新的时候触发,即state树发生变化时触发
// 在异步模式下使用componentWillUpdate都是不安全的,因为外部回调可能会多次调用只更新一次
UNSAFE_componentWillUpdate(nextProps, nextState) {
setTimeout(() => {
console.log('componentWillUpdate:', '\n新的state', nextState, '\n新的props', nextProps)
}, 1500)
}
// 组件更新结束之后执行,在初始化render时不执行
componentDidUpdate(prevProps, prevState) {
// 如果不在此处限制条件的话 DidUpdate生命周期后会不断执行
if (this.state.flagCount < 1) {
setTimeout(() => {
this.setState({
title: 'componentDidUpdate',
flagCount: this.state.flagCount + 1
})
console.log('componentDidUpdate:\n之前的props', prevProps, '\n之前的state', prevState, '\n更新后的state', this.state)
}, 1500)
}
}
// 组件第一次加载完成
// 在这里调用接口数据请求和进行事件监听
// 有一个常见的错误观念认为,在componentWillMount中提取可以避免第一个空的渲染。
// 在实践中,这从来都不是真的,因为React总是在componentWillMount之后立即执行渲染。
// 如果数据在componentWillMount触发的时间内不可用,则无论你在哪里提取数据,第一个渲染仍将显示加载状态。
// 这就是为什么在绝大多数情况下将提取移到componentDidMount没有明显效果。
componentDidMount = () => {
setTimeout(() => {
this.setState({
title: 'componentDidMount',
})
console.log('componentDidMount')
}, 1500)
};
// 组件卸载后执行
// 人们经常认为componentWillMount和componentWillUnmount总是配对,但这并不能保证。
// 只有调用componentDidMount后,React才能保证稍后调用componentWillUnmount进行清理。
// 出于这个原因,添加事件监听的推荐方式是使用componentDidMount生命周期:
//如果想要添加事件监听函数,请移步到componentDidMount生命周期,
//在这里添加的话会导致服务器渲染(componentWillUnmount永远不会被调用)
//异步渲染(在渲染完成之前渲染可能被中断,
//导致componentWillUnmount不被调用)的内存泄漏。
componentWillUnmount() {
this.setState({
title: 'componentWillUnmount'
})
console.log('componentWillUnmount ')
}
// 新的静态getDerivedStateFromProps生命周期在组件实例化以及接收新props后调用。
// 它可以返回一个对象来更新state,或者返回null来表示新的props不需要任何state更新。
// 与componentDidUpdate一起,这个新的生命周期应该覆盖传统componentWillReceiveProps的所有用例。
static getDerivedStateFromProps(nextProps, prevState) {
console.log('getDerivedStateFromProps', nextProps, prevState)
if (nextProps.value !== prevState.value) {
return {
value: nextProps.value
}
}
return null
}
// 新的getSnapshotBeforeUpdate生命周期在更新之前被调用(例如,在DOM被更新之前)。
// 此生命周期的返回值将作为第三个参数传递给componentDidUpdate。
//(这个生命周期不是经常需要的,但可以用于在恢复期间手动保存滚动位置的情况。
// 与componentDidUpdate一起,这个新的生命周期将覆盖旧版componentWillUpdate的所有用例
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate', prevProps, prevState)
return null
}
render() {
setTimeout(() => {
console.log('render')
}, 1500)
return [
this.state.flagCount == 1 ?
[
<input key="input" style={{width:200}} type="text" placeholder="我是新的ref属性绑定方法的input" ref={this.inputRef} />,
<input key="inputbefore" style={{width:300}} type="text" placeholder="早前绑定ref使用回调:node=>this.input=node" ref={node=>this.inputBefore=node} />,
<p key="p" ref={this.textRef}>我是一段文本,ref属性绑定的是this.textRef</p>,
<h1 key="0">{this.state.flagCount}</h1>,
<div key="1">当前生命周期: {this.state.title}</div>,
<div key="2">{this.props.value}</div>,
<button key="3" onClick={this.props.click}>点击模拟更新props</button>,
<button key="4" onClick={_=>this.inputRef.current.focus()}>点击让input获得焦点</button>,
<button key="6" onClick={_=>console.log(this.textRef)}>打印文本ref对象</button>
]:<p key="5">loading.....</p>
]
}
}
父组件引用的地方:
import ComponentLifeCycle from './componentlife'
export default class Test extends Component {
state = {
count: 0
}
count = () => {
if (this.state.count < 20) {
this.setState({
count: this.state.count + 1
})
}
};
render() {
return [
<ComponentLifeCycle
key="0"
value={this.state.count}
click={this.count}
/>,
]
}
}