學習React有一個很重要的概念須要弄清楚,那就是React組件的生命週期,以及它跟 setState 所引發的 React生命週期鉤子的調起狀況。React 生命週期分爲掛載階段、更新階段和卸載階段。下面我將使用 create-react-app
作一個簡單的分析,React版本是16.8.1
。css
核心代碼以下,簡單輸出各生命週期鉤子的日誌信息:react
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count:0
};
console.log('constructor')
}
componentWillMount(){
console.log('componentWillMount')
}
componentDidMount() {
console.log('componentDidMount')
}
//WARNING! To be deprecated in React v17. Use componentDidUpdate instead.
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate')
}
componentDidUpdate(){
console.log('componentDidUpdate')
}
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps')
}
render() {
console.log('render', this.state)
return (
<div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> <button onClick={this.handleClick}>click me</button> </header> </div> ); } } export default App; 複製代碼
瀏覽器輸出日誌以下,結果很簡單明瞭: 瀏覽器
componentWillMount
中setState更新狀態會怎麼樣呢?componentWillMount(){
console.log('componentWillMount')
this.setState({foo: 'bar'});
}
複製代碼
瀏覽器輸出日誌以下,能夠看到在componentWillMount
中更新狀態不會觸發更新過程,但新的狀態會及時在 render 中體現:bash
在這裏,咱們須要注意到 setState 是異步的操做:服務器
componentWillMount(){
console.log('componentWillMount')
console.log('componentWillMount before setState',this.state)
this.setState({foo: 'bar'});
console.log('componentWillMount after setState',this.state)
}
複製代碼
瀏覽器輸出日誌以下,能夠看到執行setState操做後,state 對象沒有當即生效,而是到了 render 函數中才生效。app
componentWillMount(){
console.log('componentWillMount')
console.log('componentWillMount before setState',this.state)
this.setState({foo: 'bar'},() => {
console.log('componentWillMount after setState',this.state)
});
}
複製代碼
componentWillMount(){
console.log('componentWillMount')
this.setState({foo: 'bar'});
this.setState({foo: 'bar2'});
}
複製代碼
能夠在此看處 setState後於console.log('do some calculate or other operation...')
執行,再次反映了 setState的異步執行機制。這裏,透露了一個最佳實踐建議,即:dom
在 setState 以前作好計算,最後再一次性 setState。這樣,代碼順序就和執行順序一致,出問題時纔不會一臉懵逼。異步
componentDidMount
組件掛載完成後執行,能夠在這裏拉取服務器數據(固然,也能夠在上面提到的componentWillMount
中拉取遠程數據)。也能夠在這裏添加對dom 的監聽及其餘對dom 的操做,還能夠建立定時器。(相應的,須要在componentDidMount
中銷燬 dom 的監聽和 timer,以避免形成內存泄漏。若是代碼更嚴謹一點,可同時在 componentWillMount 和 componentDidMount 中銷燬 dom 的監聽和 timer,以避免某些狀況下 componentDidMount 沒有執行。)svg