组件的生命周期

挂载

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

componentWillMount() 之后将废弃

更新

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

componentWillUpdate() 、 componentWillReceiveProps() 之后将被废弃

卸载

当组件从 DOM 中移除时会调用如下方法:

  • componentWillUnmount()

错误处理

当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:

  • static getDerivedStateFromError()
  • componentDidCatch()

组件还提供了一些额外的 API:

  • setState()
  • forceUpdate()

单独介绍

getDerivedStateFromProps

这个生命周期函数是为了替代 componentWillReceiveProps 存在的,所以在你需要使用componentWillReceiveProps的时候,就可以考虑使用getDerivedStateFromProps来进行替代了。

两者的参数不相同的,而getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。

而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state。

需要注意的是,如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾。

static getDerivedStateFromProps(nextProps, prevState) {
const {type} = nextProps;
// 当传入的type发生变化的时候,更新state
if (type !== prevState.type) {
return {
type,
};
}
// 否则,对于state不进行任何操作
return null;
}

如果你的组件内部既需要修改自己的type,又需要接收从外部修改的type。

static getDerivedStateFromProps(nextProps, prevState) {
const {type} = nextProps;
// type可能由props驱动,也可能由state驱动,这样判断会导致state驱动的type被回滚
if (type !== prevState.type) {
return {
type,
};
}
// 否则,对于state不进行任何操作
return null;
}

在非必须的时候,摒弃这种写法。type要么由props驱动,要么完全由state驱动。

如果实在没有办法解耦,那么就需要一个hack来辅助:绑定props到state上。

constructor(props) {
super(props);
this.state = {
type: 0,
props,
}
}
static getDerivedStateFromProps(nextProps, prevState) {
const {type, props} = nextProps;
// 这段代码可能看起来非常混乱,这个props可以被当做缓存,仅用作判断
if (type !== props.type) {
return {
type,
props: {
type,
},
};
}
// 否则,对于state不进行任何操作
return null;
}

上面的代码可以保证在进行多数据源驱动的时候,状态能够正确改变。当然,这样的代码很多情况下是会影响到别人阅读你的代码的,对于维护造成了非常大的困难。

getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。

应返回 snapshot 的值(或 null)。

class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
} getSnapshotBeforeUpdate(prevProps, prevState) {
// 我们是否在 list 中添加新的 items ?
// 捕获滚动位置以便我们稍后调整滚动位置。
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
} componentDidUpdate(prevProps, prevState, snapshot) {
// 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
// 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
//(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
} render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}

在上述示例中,重点是从 getSnapshotBeforeUpdate 读取 scrollHeight 属性,因为 “render” 阶段生命周期(如 render)和 “commit” 阶段生命周期(如 getSnapshotBeforeUpdate 和 componentDidUpdate)之间可能存在延迟。

Error boundaries

Error boundaries 是 React 组件,它会在其子组件树中的任何位置捕获 JavaScript 错误,并记录这些错误,展示降级 UI 而不是崩溃的组件树。Error boundaries 组件会捕获在渲染期间,在生命周期方法以及其整个树的构造函数中发生的错误。

如果 class 组件定义了生命周期方法 static getDerivedStateFromError()componentDidCatch() 中的任何一个(或两者),它就成为了 Error boundaries。通过生命周期更新 state 可让组件捕获树中未处理的 JavaScript 错误并展示降级 UI。

仅使用 Error boundaries 组件来从意外异常中恢复的情况;不要将它们用于流程控制。

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;
}
}

注意:getDerivedStateFromError() 会在渲染阶段调用,因此不允许出现副作用。 如遇此类情况,请改用 componentDidCatch()。

componentDidCatch(error, info)

componentDidCatch() 会在“提交”阶段被调用,因此允许执行副作用。 它应该用于记录错误之类的情况:

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的异步操作

因为setState是异步的,所有有时setState后获取this.state数据并不准确,可以如下操作:

state = {
name:'initName'
} this.setState((state,props)=>{
console.log(state,props);
return {name:'name-change'};
}) const {name}=this.state;
this.setState({name:'name-change'},()=>{
console.log(this.state.name,name) // name-change initName
})

官方文档:https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops

React.Component(V16.8.6)的更多相关文章

  1. webpack学习(六)—webpack+react+es6(第3篇)

    接上篇 : webpack学习(六)—webpack+react+es6(第2篇) 上篇其实是有问题的,问题在取服务器数据这块.this.props 表示那些一旦定义,就不再改变的特性,而 this. ...

  2. webpack学习(六)—webpack+react+es6(第2篇)

    接上篇        webpack学习(五)—webpack+react+es6(第1篇) 本文做个简单的图片加文字的页面.其中,配置文件跟上篇一致.项目结构: index.html <!DO ...

  3. webpack学习(五)—webpack+react+es6(第1篇)

    如果你看过webpack学习系列的前一个文章,接下来做的东西会比较简单 :webpack学习(四)— webpack-dev-server react发展的很快,现在大部分开发react相关的项目,都 ...

  4. React Autocomplete(自动完成输入)示例教程

    React Autocomplete示例教程是今天的主题.在现代Web开发中,使用React改善用户体验是很容易.自动完成的概念很简单.它是基于用户输入的建议列表.然后,用户可以按Enter键以完成短 ...

  5. React HOC(高阶组件)

    一.定义 高阶函数:函数接受函数作为输入,或者输出一个函数. 高阶组件:接受React组件作为输入,或是输出一个组件.即hocFactory:: W: React.Component => E: ...

  6. React介绍(讲人话)

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 21.0px "PingFang SC"; color: #616161 } span. ...

  7. 学习React系列(一)——React.Component 生命周期

    挂载中(只执行一次) 以下方法在组件实例正被创建和插入到DOM中时调用 constructor()一般用于初始化state和方法的this绑定 componentWillMount() render( ...

  8. React.Component 与 React.PureComponent(React之性能优化)

    前言 先说说 shouldComponentUpdate 提起React.PureComponent,我们还要从一个生命周期函数 shouldComponentUpdate 说起,从函数名字我们就能看 ...

  9. ReactJs 的各个版本生命周期、API变化 汇总(一、V16.0.0)

    目录 一.React 各个版本之间的纵向对比 二.React 的基础 1.Components and Props 三.React V 16.0.0 1. The Component Lifecycl ...

随机推荐

  1. 通过request获取ID地址的方法

    // 获取IP地址 public static String getIpAddr(HttpServletRequest request) {  String ip = request.getHeade ...

  2. Centos7搭建Mysql-5.6.38,及主从复制。

    Server1:192.168.1.189  (主) Server2:192.168.1.190  (从) 1.关闭默认的firewalld防火墙,安装iptables. systemctl disa ...

  3. Git_错误_03_ Git提交时显示用户 unknown

    这是因为没有设置用户名 $ git config --global user.name "your_name" $ git config --global user.email & ...

  4. java String final + equal == 区别

    java String 是不可改变的类型. String a = "hello2"; String d = "hello"; final String b = ...

  5. yahoo的30条优化规则

    1.尽量减少HTTP请求次数 终端用户响应的时间中,有80%用于下载各项内容.这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数.这是提高网页速 ...

  6. uimsbf和 bslbf的含义

    bslbf代表位串,即“Bit string, left bit first ”, uimsbf代表无符号整数,即”unsinged integer, most significant bit fir ...

  7. bzoj5329 战略游戏

    有一个圆方树,每次给出一个点集,询问虚树上圆点数量-询问点数量 sol:题意读懂就很简单了...可以建虚树dp 也可以考虑每一条链对答案的贡献,最后要注意单独计算虚树根对答案的贡献 #pragma G ...

  8. Hihocoder1662 : 查找三阶幻方([Offer收割]编程练习赛40)(暴力)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个N x M的矩阵,请你数一数其中有多少个3 x 3的子矩阵可以构成三阶幻方? 如果3 x 3的矩阵中每一行.每一列 ...

  9. 1045 Favorite Color Stripe (30)(30 分)

    Eva is trying to make her own color stripe out of a given one. She would like to keep only her favor ...

  10. C#SqlDataReader的用法

    string sqljn = "select [序号],[品名],[电压等级],[单位],[型号],[规格],[红本价格] FROM [book].[dbo].[View_wjprice]& ...