constructor
React借用class
类的constructor
充当初始化钩子。在我们类扩展任何其他具有已定义构造函数的类的情况下,调用一个特殊的函数super
非常重要。
在React
中,因为所有class
组件都要继承自Component
类或者PureComponent
类,因此和原生class写法一样,要在constructor里首先调用super
方法,才能获得this
。
deprecated—componentWillMount
componentWillMount
与构造函数没有太大的区别——它也只在初始安装生命周期中调用一次。
许多人会在这个函数中发送请求来获取数据,并期望在初次渲染就绪之前数据是可用的。
事实并非如此,尽管请求将在初次渲染之前被初始化,但在有时调用render
之前它无法完成。
由于这一事实,不建议使用此函数可能会导致操作的副作用。
需要注意的是,在服务端渲染时调用此函数,而在这种情况下,不会在服务器上调用对应的componentDidMount,而是在客户端上调用。
在这个函数中使用setState
不会触发render
static getDerivedStateFromProps(nextProps, prevState)
这个新的方法根据父组件传来的props按需更新自己的state,主要是来代替componentWillReceiveProps
。
该方法定义的时候要加一个static
关键字,访问不到this
对象,在使用的时候,返回一个对象来增量更新组件的state
(和setState
非常像)
render
千万不要在render
生命周期钩子里调用setState
,因为setState
会引发render
,这样就没完没了。
componentDidMount
在组件挂载之后调用,并且只调用一次。
因为这个函数只保证被调用一次,所以它在这里执行ajax
请求简直是完美。
deprecated—componentWillReceiveProps(nextProps)
在每次收到props
(父组件重新渲染)的时候,在每个更新生命周期中都会调用此函数,而且会传递所有的props
,无论props
的值是否发生了改变,简单来说就是组件收到新的props
或者父组件重新渲染,都会触发这个方法。
如果某个组件的部分state
是依赖于父组件中传递过来的props
,这个函数是理想的。
- 注意:即使
props
没有发生变化,在componentWillReceiveProps
也会被调用,这就需要开发者来判断其值是否已经发生改变。
componentWillReceiveProps(nextProps) {
if(nextProps.myProp !== this.props.myProps) {
// do something
}
}
shouldComponentUpdate(nextProps, nextState, nextContext)
默认情况下,所有基于Components
的类在收到props
时,state
或context
改变时,都会触发render
。如果重新渲染组件涉及的计算比较复杂(比如生成图表)或者由于某些性能原因而不推荐,则开发人员就需要来控制一下了。当shouldComponentUpdate
返回false
的时候,就不会触发render
。
React
还提供了一个PureComponent
,它与Component
的区别是PureComponent
自动实现了一个shouldComponentUpdate
。
shouldComponentUpdate
暴露了两个参数,开发者可以通过比较props
和nextProps
、state
和nextState
来判断状态到底有没有发生改变,再返回true
或false
。要注意一下引用的坑。
deprecated — componentWillUpdate(nextProps, nextState)
shouldComponentUpdate
生命周期钩子返回true,或者调用this.forceUpdate之后,会立即执行该生命周期钩子。
要特别注意,componentWillUpdate
生命周期钩子每次更新前都会执行,所以不能在这里调用setState
,有可能会没完没了。
同样,因为Fiber机制的引入,这个生命周期钩子有可能会多次调用。
componentDidUpdate(nextProps, nextState, snapshot)
componentWillUnmount
这是组件卸载之前的生命周期钩子。
React的最佳实践是,组件中用到的事件监听器、订阅器、定时器都要在这里销毁。
componentDidMount() {
document.addEventListener('click', () => {});
}
componentDidCatch
在过去,组件内部的JavaScript错误总是扰乱组件状态以至于在下一次渲染中出现一些奇怪的错误,而且这些错误常常由应用中一些更早的错误引起,然而 React 没有提供一种在组件内部解决这些问题的优雅方案,也不能从错误中恢复。
用户界面某处的 JavaScript 错误不应该使整个 APP 崩溃,为了解决这个问题,React16 引进了一个新的概念 —— Error Boundaries
Error Boundaries 可以捕获在其子组件树里抛出的任何错误,打印这些错误,并且返回一个展示错误的界面而不是崩溃掉的页面。Error Boundaries 可以在渲染过程中、在生命周期方法中、以及其子组件的 constructor 中捕获错误
添加了一个叫做 componentDidCatch(error, info)
的新生命周期方法的组件就叫做 Error Boundaries
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// Display fallback UI
this.setState({ hasError: true });
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
你仍然可以像正常组件一样使用它
<ErrorBoundary>
<App />
</ErrorBoundary>
componentDidCatch()
方法就像是为组件定制的 JavaScript 中的 catch {} 代码块,只有通过 class 定义的组件才能成为 Error Boundaries,在实践中,绝大多数时候你都希望只定义一个 Error Boundary 然后在应用的里使用。
生命周期
React
的生命周期钩子,实际上只有三个过程:
- 挂载
- 更新
- 卸载
老生命周期
-
挂载
- constructor
- componentWillMount
- render
-
componentDidMount
挂载
-
更新
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
-
componentDidUpdate
父组件触发`render`
`setState`触发`render`
调用`forceUpdate`触发
-
卸载
- componentWillUnmount
新生命周期
- 挂载
- constructor
- componentWillMount
- render
- componentDidMount
- 更新
-
static
getDerivedStateFromProps - shouldComponentUpdate
- render
- componentDidUpdate
-
- 卸载
-
componentWillUnmount
new-lifecycle.png
-
最后借一下大佬的图。
网友评论