一、生命周期图谱
附上官网链接,如果有侵权或者冒犯,请及时提出,我会马上做出调整。
projects.wojtekmaj.pl/react-lifec…
二、组件的生命周期
每个组件都包含生命周期方法,可以重写这些方法,以便在运行过程中特定的阶段执行这些方法。React生命周期从广义上分为三个阶段:挂载、更新、卸载。
挂载:
当组件实例被创建并插入DOM中时, 其生命周期调用顺序如下:
- construtor()
- static getDerivesStateFromProps()不常用的生命周期
- render()
- componentDidMount()
更新
当组件props或者state发生变化时会自动触发更新。组件更新的生命周期调用顺序如下:
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
卸载
- componentWillUnMount
错误处理
- static getDerivedStateFromError()
- compinentDidCatch()
其他APIS
- setState()
- forceUpdate()
三、挂载过程
- constructor():数据的初始化
如果组件不初始化state或不进行方法的绑定, 则不需要为React组件实现构造函数。
在React组件挂在之前,会调用他的构造函数。在为React.Component子类实现构造函数时,应在其他语句之前调用super(props)。否则, this.props在构造函数中可能出现未定义的bug。
- 调用constructor时,super(props)应该在最前边
下图的图中的例子,是错误的使用方式。因为此时的this实例还没有注册。所以会报Must call super constructor in derived class before accessing 'this' or returning from derived constructor的错误
下图的图中的例子,才是正确的使用方式。如果重写了constructor构造函数的话,一定要显示的继承父类。
通常,在React中, 构造函数仅用于以下两种情况:
- 通过this.state赋值对象来初始化内部state
- 为事件处理函数绑定实例。
注意事项:
- 在constructor中不要调用setState方法,如果你的组件需要使用内部state,请直接在构造函数中为this.state赋值初始化state。因为此时组件还尚未挂载。setState无法在尚未挂在的组件上调用。
- 避免将props的值赋值给state,因为props的改变不会影响到state数据对象。产生不渲染的bug
2.static getDerivedStateFromProps(props, state)
static getDerivedStateFromProps会在调用render方法之前调用,并且在初始挂载及后续更新时都会被调用。他应返回一个对象来更新state,如果返回null则不更新任何内容。
此方法无权访问组件实例。也就是不可以使用this。
大概理解是因为:
- static属于类,而this属于类实例化后的对象。
- static始终在内存上, 而this实例是只有当类创建实例后, 才会存在。
- static是该类的所有的实例的共享区域,所以在static中,是无法找到对应的实例对象的。
注意:在静态方法中,由于没有this。所以不能在调用setState,那我们可以使用return语句
返回对应的state数据。例如下图
3.render()
render方法是class组件中唯一必须实现的方法。
当render被调用时, 它会检查this.props和this.state的变化返回以下类型:
- React元素。
- 数组或Fragments,使render可以返回多个元素
- Portals可以渲染子节点到不同的DOM子树中
- 字符串或者数值类型。
- 布尔或者null
render()函数应为纯函数,这意味着在不修改组件的state的情况下,每次调用时,都返回相同的结果,并且不要直接操作dom元素。(document.getElementsById("")等方式)。如果需要操作dom,可以在componentDidMount或者componentdidUpdate等生命周期中使用。
注意:如果shouldComponentUpdate()返回false,则不会调用render()方法。
4.componentDidMount
componentDidMount()会在组件挂载后(初次渲染,已经渲染到页面后)立即调用。
此生名周期适合dom节点的初始化,比如请求数据等。也适合添加订阅。如果添加了订阅,请在卸载生命周期componentUnMount()里取消订阅。
5.shouldComponentUpdate()
默认返回boolean类型值为true,只要props或者state改变,都会在渲染之前触发该方法。
首次渲染或者forceUpdate()不会调用该方法
如果重写该方法并且返回false,或者不显示的返回true,该组件的render、componentWillUpdate、componentDidUpdate则不会被触发调用。因为返回false就是不去渲染。
6.getSnapshotBeforeUpdate(preProps,preState)
在最近一次渲染输出之前调用。此生命周期的任何返回值都作为参数传递给componentDidUpdate()
7.componentDidUpdate(PreProps, preState, snapshot)
会在更新后立即调用,首次渲染不执行此方法。
当组件更新后,可以在此处对dom进行操作。
可以在此调用setState,但要判断好,否则死循环了。
如果组件实现了 getSnapshotBeforeUpdate生命周期(不常用),则它的返回值将作为 componentDidUpdate 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined。
8.componentWillUnMount()
会在组件卸载及销毁之前调用。此方法中可以取消订阅。在此方法中不要调用setState了。因为该组件不会再重新渲染了。
9.static getDerivedStateFromError(error)
此生命周期会在后代组件抛出错误后被调用。它将抛出的错误作为参数。
捕获到错误,可以渲染任何自定义的降级ui。
10.componentDidCatch(error, info)
此生命周期会在后代组件抛出错误后被调用。该生命周期会在‘提交阶段’被调用(更新阶段的渲染后的生命周期)
注意过时的生命周期方法,在新的代码中避免使用。
- UNSAFE_componentWillMount()
- UNSAFE_componentWillUpdate()
- UNSAFE_componentWillreceiveProps()