理解React-组件生命周期

做者-Bartosz Szczeciński原文react

React提供给开发者不少方法或‘钩子’,调用于一个组件的生命周期,使咱们更新UI和app state。了解什么时候使用哪些对正确理解如何使用React相当重要。git

constructor

constuctors是OOP的基础——一个不管什么时候一个新object被建立时被调用的特殊函数。调用一个特殊函数super很是重要,在咱们的class extent任何其它class(也有定义了constructor)时。调用此特殊函数将call 咱们parent class的constructor且容许初始化其自己。此即为什么咱们只有在初始化地call了super时才有权限访问this.props的缘由。github

如上所述,constructor对于构建咱们组件——建立任何领域(以this.开始的变量)或者初始化以接收到的props为基础的state——很是完美。redux

这也是你经过在直接覆盖this.state之处期待change/set state仅有的字段。在别的其它实例上记得用this.setState.bash

DO服务器

  • set initial state
  • 若未用class属性语法-准备全部class 字段和bind 将做为callback传递的函数。

DON'Tapp

  • cause any side effects (AJAX calls etc.)

componentWillMount

这是一个特殊状况 - componentWillMount与构造函数没有多大区别 - 它只在初始安装生命周期中被调用一次。 从历史上看,使用componentWillMountover构造函数有一些缘由,请参阅此react-redux问题,但请记住,此处描述的练习已被弃用。ide

不少人会试图使用这个函数来发送请求来获取数据,并但愿在初始渲染准备好以前数据可用。 状况并不是如此 - 当请求在渲染以前被初始化时,在渲染被调用以前它将不能完成。函数

此外,随着对React Fiber的更改(post React 16 beta版本),此函数最终可能会在初始渲染被调用以前调用屡次,所以可能会致使触发多重反作用。 因为这个事实,不推荐使用这个函数来产生任何反作用。post

值得注意的是,在使用服务器端渲染时调用此函数,而在这种状况下,它不会在服务器上调用对应的componentDidMount,而是在客户端上调用。 因此若是在服务器部分须要一些反作用,这个函数应该被用做例外。

此函数中使用的setState是“空闲”的,不会触发从新渲染。

DO

  • update state 经过 this.setState
  • perform last minute optimization(执行最后一分钟优化)
  • 仅在SSR形成side-effects (AJAX calls etc.)

DON'T

  • 不在CS形成side-effects (AJAX calls etc.)

componentWillReceiveProps(nextProps)

这个函数将在每一个更新生命周期中由props变化(父元素从新渲染)调用,而且将传递全部props传递的对象图,不管自上次从新渲染后props值是否已经改变亦或自前个渲染阶段。

这个函数是理想的,若是你有一个组件的状态部分取决于从父组件传递的props做为调用this.setState在这里不会致使额外的渲染调用。

请记住,因为全部props都调用了该函数,因此即便对那些没有改变的props,开发人员也会执行检查以肯定实际值是否发生了变化,例如:

componentWillReceiveProps(nextProps) {
  if(nextProps.myProp !== this.props.myProps) {
    // nextProps.myProp has a different value than our current prop
    // so we can perform some calculations based on the new value
  }
}
复制代码

因为使用React Fiber(16阶测试版)这个功能可能会在实际调用renderfunction以前屡次调用,所以不建议在此使用任何反作用致使的操做。

DO

  • sync state to props(同步化state到props)

DON'T

  • 形成side-effects (AJAX calls etc.)

shouldComponentUpdate(nextProps, nextState, nextContext)

默认状况下,全部基于类的组件都会在它们接收到的props,其状态或环境发生变化时从新render本身。 若是从新渲染组件是计算重启(例如生成图表)或者出于某些性能缘由不推荐使用,则开发人员能够访问将在update cycle中调用的特殊函数。

这个函数将在内部调用props,state和object的下一个值。 开发人员可使用它们来验证更改是否须要从新渲染,并返回false以防止从新渲染发生。 在其余状况下,您预计会返回true。

DO

  • 用于提升perfomance

DON'T

  • 形成side-effects (AJAX calls etc.)
  • call this.setState

componentWillUpdate(nextProps, nextState)

若是shouldComponentUpdate函数未被使用,或者它决定组件在此渲染周期中应更新,则将调用另外一个生命周期函数。 此函数一般用于在state的某些部分基于props时,执行状态和props同步。

在实现shouldComponentUpdate的状况下,可使用此函数而不是componentWillReceiveProps,由于只有在实际从新渲染组件时才会调用此函数。

与全部其余componentWill *函数相似,此函数可能在渲染前最终调用屡次,所以不建议在此执行致使操做的反作用。 DO

  • synchronize state to props

DON'T

  • 形成side-effects (AJAX calls etc.)

componentDidUpdate(prevProps, prevState, prevContext)

这个函数将在渲染完成后在每一个从新渲染周期中被调用。 这意味着您能够肯定组件及其全部子组件已正确render其自身。

因为这是惟一保证在每一个从新render周期中仅被调用一次的函数,所以建议将此函数用于任何致使操做的反作用。 与componentWillUpdate和componentWillReceiveProps相似,即便这些值没有发生实际更改,也会使用之前的props,state和context的object映射来调用此函数。 由于开发人员须要手动检查给定的值是否发生了变化,而后才能执行各类更新操做:

componentDidUpdate(prevProps) {
  if(prevProps.myProps !== this.props.myProp) {
    // this.props.myProp has a different value
    // we can perform any operations that would 
    // need the new value and/or cause side-effects 
    // like AJAX calls with the new value - this.props.myProp
  }
}
复制代码

DO

  • 形成side-effects (AJAX calls etc.)

DON'T

  • call this.setState 因其可致re-render

上述规则的一个例外是基于某些DOM属性更新状态,只有在组件从新呈现后才能计算该属性(例如,某些DOM节点的位置/维度)。 请注意防止更新,若是值实际上没有更改,可能会致使渲染循环。

componentDidCatch(errorString, errorInfo)

React 16中的新增功能 - 今生命周期方法的特殊之处在于它能够对发生在子组件中的事件做出反应,特别是对任何子组件中发生的任何未捕获错误。

经过这个添加,你可让你的父母元素处理错误 - 例如 - 设置错误信息状态并在其渲染中返回适当的消息,或者登陆到报告系统,例如:

componentDidCatch(errorString, errorInfo) {
  this.setState({
    error: errorString
  });
  ErrorLoggingTool.log(errorInfo);
}
render() {
  if(this.state.error) return <ShowErrorMessage error={this.state.error} />
  return (
    // render normal component output
  );
}
复制代码

发生错误时,该函数将被调用:

  • errorString - 错误的.toString()消息
  • errorInfo - 具备单个字段componentStack的对象,它表示堆栈跟踪返回错误发生的位置,例如:
in Thrower
    in div (created by App)
    in App

复制代码

componentDidMount

这个函数在给定组件的整个生命周期中只会被调用一次,而且它被调用表示组件及其全部子组件被正确渲染。

因为这个函数被保证只被调用一次,所以它是完成AJAX请求等引发反作用的操做的理想选择。

DO

  • 形成side-effects (AJAX calls etc.)

DON'T

  • call this.setState 因其可致re-render

上述规则的一个例外是基于某些DOM属性更新状态,只有在组件从新呈现后才能计算该属性(例如,某些DOM节点的位置/维度)。 请注意防止更新,若是值实际上没有更改,可能会致使渲染循环。

componentWillUnmount

若是它使用定时器(setTimeout,setInterval),打开套接字或执行咱们须要在再也不须要时关闭/移除的任何操做,则使用此函数在组件后面“清除”。

DO

  • remove any timers or listeners created in lifespan of the component

DON'T

  • call this.setState, start new listeners or timers

Component cycles

组件可能re-render有多种缘由,而且每一个组件中都会调用不一样的函数,以便开发人员更新组件的某些部分。

  • Component creation(组件建立)

第一个循环是组件的建立,这一般是在解析的JSX🌲中第一次遇到组件时发生的:

  • Component re-rendering due to re-rendering of the parent component(因为父组件更新而组件更新)

  • Component re-rendering due to internal change (e.g. a call to this.setState())( 因为内部改变的组件更新)

  • Component re-rendering due to call to this.forceUpdate(因为call this.forceUpdate而re-render的组件)

  • Component re-rendering due to catching an error(因为捕获错误而更新组件)

在React 16中引入了“ErrorBoundaries”。 一个组件能够定义一个特殊的层,它能够捕获错误并提供一个新的生命周期方法 - componentDidCatch - 它容许开发人员提供自我修复操做以恢复或优雅地处理错误。

Shoutout to@James_k_nelson,他刚刚发布了一个componentWillReceiveProps模拟器,你能够在reactarmory.com/guides/life…找到并使用它。

相关文章
相关标签/搜索