博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React.Component(V16.8.6)
阅读量:5318 次
发布时间:2019-06-14

本文共 5218 字,大约阅读时间需要 17 分钟。

组件的生命周期

挂载

当组件实例被创建并插入 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 (      
{/* ...contents... */}
); }}

在上述示例中,重点是从 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 

Something went wrong.

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

Something went wrong.

; } 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://www.cnblogs.com/adoctors/p/10976931.html

你可能感兴趣的文章
函数之匿名函数
查看>>
shell习题第16题:查用户
查看>>
实验4 [bx]和loop的使用
查看>>
Redis常用命令
查看>>
2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)
查看>>
2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
查看>>
redis cluster 集群资料
查看>>
微软职位内部推荐-Sr. SE - Office incubation
查看>>
微软职位内部推荐-SOFTWARE ENGINEER II
查看>>
centos系统python2.7更新到3.5
查看>>
【Quartz】常用方法的使用方式(三)
查看>>
MVVM模式下关闭窗口的实现
查看>>
C#区域截图——调用API截图
查看>>
c#与java中byte字节的区别及转换方法
查看>>
A WebBrowser Toy
查看>>
用MyXls生成Excel报表(C#)
查看>>
了解WP的传感器
查看>>
阅读笔记 火球——UML大战需求分析 2
查看>>
acedEvaluateLisp函数的反汇编
查看>>
Linux无线工具详解(Wireless tools for Linux)
查看>>