组件的生命周期
getDefaultProps
: 初始化 propsconstructor
:可以初始化 state 使用 constructor 必须搭配 super(),否则 this 会报错getDeravedStateFromProps
:映射 props 到 statecomponentDidMount
shouldComponentUpdate
getSnapshotBeforeUpdate
:在更新之前获取快照componentDidUpdate
componentDidCatch
1、如果上述的钩子都存在,在组件渲染过程中,会先走
constructor
处理里面的逻辑,例:设置初始的state
2、再执行getDerivedStateFromProps
钩子,return prevProps
的操作就是将props
的内容映射到state
中,使用getDerivedStateFromProps
钩子,需要先使用this.state
3、组件渲染的过程中都会走一遍componentDidMount
钩子
4、如果有操作触发state
更新,钩子会从getDerivedStateFromProps
开始处理
5、再执行shouldComponentUpdate
钩子 满足条件后返回 true 触发更新 走 render 函数
6、render
之后还要看是否有进一步的更新操作
7、看是否有getSnapshotBeforeUpdate
钩子拦截 它的返回值就是componentDidUpdate
钩子的第三个参数snapshot
8、不管是否有getSnapshotBeforeUpdate
, 都会继续走到componentDidUpdate
钩子,如果在这个过程中还有操作引起state
的内容变化,会再次从getDerivedStateFromProps
—shouldComponentUpdate
—render
—getSnapshotBeforeUpdate
—componentDidUpdate
class App extends React.Component {
static defaultProps = {
name: "amin",
unmount: false
}
constructor(props) {super(props);
console.log(1)
this.state = {num: 1}
}
static getDerivedStateFromProps (prevProps, prevState) {console.log(2)
return prevProps
}
componentDidMount() {console.log(3)
}
shouldComponentUpdate(nextProps, nextState, nextContext) {console.log(4)
console.log(nextProps, 'nextProps')
console.log(nextState, "nextState")
console.log(nextContext, "nextContext")
return true
}
getSnapshotBeforeUpdate(prevProps, prevState) {console.log(prevProps, "prevProps")
console.log(prevState, "prevState")
console.log(5)
return 5
}
componentDidUpdate(prevProps, prevState, snapshot) {console.log(prevProps, "prevProps")
console.log(prevState, "prevState")
console.log(snapshot, "snapshot")
console.log(6)
if (this.state.num !== snapshot) {this.setState({num: snapshot})
}
}
componentWillUnmount() {
// 组件销毁的时候执行的操作
// 清空定时器 初始化状态管理器的内容等
// 我们不能在组件销毁后设置 state!页面快速切换,有异步请求的情况下容易报这个错
this.setState({unmount: true})
}
btnClick = () => {const { num, unmount} = this.state
if (unmount) return
// 假装这里是个异步操作 组件卸载的时候 unmount 为 true 不进行下一步操作
this.setState({num: num + 1})
}
render () {const { num} = this.state
console.log(num, "num")
return (
<div>
<div>{num}</div>
<button onClick={this.btnClick}>+</button>
</div>
)
}
}
export default App;
componentDidCatch
可以拦截报错信息,防止出现页面级崩溃,在开发环境中使用,会一闪而过,打包之后在生产环境即可生效
import React from 'react';
class Children extends React.Component {constructor(props) {super(props);
this.state = {num: 0}
}
componentDidMount() {}
onPress = () => {
let newNum = this.state.num + 1
this.setState({num: newNum},()=>{if (this.state.num === 5){throw new Error('崩溃:Did you report the error today')
}
})
}
render() {
return (
<ErrorWrap>
<button onClick={this.onPress}>
<div> 点到崩溃 </div>
</button>
正常
</ErrorWrap>
)
}
}
class ErrorWrap extends React.Component {constructor(props) {super(props);
this.state = {error: null}
}
componentDidCatch(error, errorInfo) {console.log(error)
this.setState({error})
}
render () {const { error} = this.state
if (error) {
return (
<div>
<div style={{color: 'red'}}>
{error && error.toString()}
</div>
</div>
);
}
return this.props.children;
}
}
class App extends React.Component {render () {
return (
<div>
<ErrorWrap>
<Children />
</ErrorWrap>
</div>
)
}
}
export default App;