组件的生命周期
getDefaultProps
: 初始化props
constructor
:可以初始化state 使用constructor必须搭配super(), 否则this会报错
getDerivedStateFromProps
:映射props到state
componentDidMount
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;