生命周期
我们先来看下React16.0前后生命周期变化的图片
生命周期图谱:http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
❶ 过时生命周期:
① componentWillMount
② componentWillReceiveProps
③ componentWillUpdate
❷ 即将过时生命周期:(在新代码中我们应该避免使用它们)
① UNSAFE_componentWillMount
② UNSAFE_componentWillReceivePorps
③ UNSAFE_componentWillUpdate
❸ 新增生命周期
① getDerivedStateFromProps
② getSnapShotBeforeUpdate
③ getDerivedStateFromError
④ componentDidCatch
老生命周期我就不赘述了,下边我归纳下我对几个新生命周期用法的理解
① static getDerivedStateFromProps(nextProps, prevState)
○ 什么时候调用?
这个方法会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
○ 返回值
返回值是必须的,它应该是一个对象,用于更新state; 如果返回值为null,state不更新。
○ 主要用途?
这个生命周期函数是为了替代componentWillReceiveProps存在的,所以在你需要使用componentWillReceiveProps的时候,就可以考虑使用getDerivedStateFromProps来进行替代。主要是将新的props更新到state上
特别说明:
它是静态方法,所以它没有this(实例对象无法访问),只能通过类名访问。
看下边例子就明白了!
class Child extends Component {
constructor(props) {
super(props);
this.state= {
info: props.info || "hello world"
}
}
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.info!== prevState.info) {
return ({
info: nextProps.info
})
}
return null;
}
render() {
return (
<p>{this.state.info}</p>
)
}
}
class App extends Component {
constructor(props) {
super(props);
this.state= {
childInfo: "Hello world"
}
}
clickHandler = () => {
this.setState({
childInfo: "Changed world"
})
};
render() {
return (
<>
<Child info={this.state.childInfo}/>
<button onClick={this.clickHandler}>Click Me</button>
</>
);
}
}
② getSnapshotBeforeUpdate(prevProps, prevState)
○ 什么时候调用?
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。
○ 返回值
应返回 snapshot 的值(或 null)
○ 有什么用途?
它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。
此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。
③ static getDerivedStateFromError(error)
○ 什么时候调用?
此生命周期会在渲染阶段后代组件抛出错误后被调用,因此不允许出现副作用。
○ 返回值
它将抛出的错误作为参数,并返回一个值以更新 state
○ 有什么用途?
主要用于封装错误边界用,收集错误信息并做对应处理。
以下为具体用法用例
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state= {hasError: false};
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染可以显降级UI
return {hasError: true};
}
render() {
if (this.state.hasError) {
// 你可以渲染任何自定义的降级UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
然后你可以将它作为一个常规组件去使用:
<ErrorBoundary>
<div>Hello world</div>
</ErrorBoundary>
④ componentDidCatch(error, info)
○ 什么时候调用?
此生命周期会在“提交”阶段后代组件抛出错误后被调用,因此允许执行副作用。
○ 参数
error —— 抛出的错误。
info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。
○ 返回值
它将抛出的错误作为参数,并返回一个值以更新 state
○ 有什么用途?
主要用于封装错误边界用,收集错误信息并做对应处理。
用例如下:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state= { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染可以显示降级UI
return { hasError: true };
}
componentDidCatch(error, info) {
// "组件堆栈" 例子:
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logComponentStackToMyService(info.componentStack);
}
render() {
if (this.state.hasError) {
// 你可以渲染任何自定义的降级UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
特别注意:
如果发生错误,你可以通过调用 setState 使用 componentDidCatch() 渲染降级 UI,但在未来的版本中将不推荐这样做。 可以使用静态 getDerivedStateFromError() 来处理降级渲染。
结论:对于新生命周期③和④作用基本是一致的,都是用于封装错误边界,收集边界下后代组件构造函数中发生的错误信息并作出对应处理。不同的是调用时间和返回参数。