react16.3开始对生命周期做了一些改动,本项目是16.8所以就用新版生命周期来说明,先上图
新建文件Mount.js
import React from 'react'; export default class Mount extends React.Component { state = { value: '' };
static getDerivedStateFromProps(props, state){
if(props.value || state.value===''){
console.log('getDerivedStateFromProps');
return {
value: 'getDerivedStateFromProps'
}
}
return true
}
shouldComponentUpdate(props, state){
console.log('shouldComponentUpdate')
if(state.value === 'getDerivedStateFromProps'){
console.log('shouldComponentUpdate')
this.setState({
value: 'shouldComponentUpdate'
})
}
return true
}
componentDidMount(){
console.log('componentDidMount');
// if(this.state.value === 'getDerivedStateFromProps'){
// this.setState({
// value: 'componentDidMount'
// })
// }
}
render(){ console.log('render'); return( <div>我是生命周期组件{this.state.value}</div> ) } }
import React from 'react'; import {Switch, Route} from "react-router-dom"; import Home2 from '../pages/Home2'; import OnePage from '../pages/OnePage'; import TwoPage from '../pages/TwoPage'; import This from '../pages/This'; import Mount from '../pages/Mount'; const Routers = ( <Switch> <Route path="/" exact component={Home2} /> <Route path="/onePage" component={OnePage} /> <Route path="/twoPage/:id" component={TwoPage} /> <Route path="/this" component={This} /> <Route path="/mount" component={Mount} /> </Switch> ); export default Routers
启动项目切换url http://localhost:3000/#/mount
F12打开控制台,打印顺序为getDerivedStateFromProps =》render=》componentDidMount,和第一张图片显示的一样,这是默认加载顺序,下面是更新顺序
我们把componentDidMount里的注释打开
componentDidMount(){
console.log('componentDidMount');
if(this.state.value === 'getDerivedStateFromProps'){
this.setState({
value: 'componentDidMount'
})
}
}
再看浏览器打印
先走getDerivedStateFromProps =》render=》 componentDidMount 正常流程走完之后,触发shouldComponentUpdate注意这里20行是进入这个生命周期但if条件不成立,
然后触发render结束,这里可以确定componentDidMount在每次更新只执行一次,我们再看如果手动让shouldComponentUpdate的if条件成立会怎么执行呢?
import React from 'react'; export default class Mount extends React.Component { state = { value: '' }; static getDerivedStateFromProps(props, state){ if(props.value || state.value===''){ console.log('getDerivedStateFromProps'); return { value: 'getDerivedStateFromProps' } } return true } shouldComponentUpdate(props, state){ console.log('shouldComponentUpdate') if(state.value === 'componentDidMount'){ console.log('shouldComponentUpdate') this.setState({ value: 'shouldComponentUpdate' }) } return true } componentDidMount(){ console.log('componentDidMount'); if(this.state.value === 'getDerivedStateFromProps'){ this.setState({ value: 'componentDidMount' }) } } render(){ console.log('render'); return( <div>我是生命周期组件{this.props.value}{this.state.value}</div> ) } }
执行顺序为
getDerivedStateFromProps =》render=》 componentDidMount =》shouldComponentUpdate注意这里if条件成立所以打印了22行代码,然后render,
但是render之后又打印了shouldComponentUpdate说明程序又进入了shouldComponentUpdate生命周期,然后if条件没有成立,继续走render,
所以shouldComponentUpdate这个生命周期必须要加if条件 否则会死循环 永远不会停止造成浏览器崩溃!!!