React 的每个组件都有自己的生命周期,从声明、挂载到卸载销毁,React 给我们提供了在不同生命周期节点进行操作的生命周期钩子,他们将在组件达到某个特定时刻的时候被触发。
生命周期图谱
挂载
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
- constructor
- render
- componentDidMount
更新
当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
- render
- componentDidUpdate
卸载
当组件从 DOM 中移除时会调用如下方法:
- componentWillUnmount
常用的生命周期方法
constructor()
React 组件的构造函数,组件被声明之后直接被调用,通常用来初始化 state
和绑定事件处理函数, 如果没有 state
并且不需要绑定事件处理函数,就不需要创建 constructor()
。
注意:在 constructor
中只能初始化 state
,不能改变 state
。即不能调用 setState()
方法
class myComponent extends React.Component {
constructor(props) {
super(props) // 优先调用
}
render() {
return ()
}
}
另外,应在其他语句之前前调用 super(props)
。否则,this.props
在构造函数中可能会出现未定义的 bug。
render()
render()
是所有生命周期中必须实现的一个方法,另外 render()
方法的变化必须只参照于 state
,也就意味着,render()
必须是一个纯函数
class myComponent extends React.Component {
render() {
return (<div>
<p>Hello World</p>
</div>)
}
}
componentDidMount()
componentDidMount()
会在组件挂载(添加到 DOM 中)后立刻调用,可以参考 Vue 中的 mounted()
,我们可以在这个方法中发送请求,进行数据交互。可以在 componentDidMount()
里直接调用 setState()
。这将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render()
两次调用的情况下,用户也不会看到中间状态。
componentDidUpdate()
componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,否则会导致死循环。
常用方式:
class myComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: 'Hello'
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(prevProps, prevState)
console.log(this.props, this.state)
if (this.props.type != prevProps.type) {
this.setState({
msg: 'Hi'
})
}
}
render() {
return <h2>{this.state.msg} World</h2>
}
}
componentWillUnmount()
componentWillUnmount()
会在组件卸载及销毁之前直接调用。componentWillUnmount()
中不应调用 setState()
,因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。