react之生命周期

1. mounting

  • constructor()
  • componentWillMount()
  • render()
  • componentDidMount()

constructor(props)

在mount之前,会调用它;

初始化state的位置;

也可以使用props来初始化state,但要注意当props更新时,state不会更新。那么除了同步props到state,还可以使用state提升。

componentWillMount()

当要mount的时候立即调用,它的调用发生在render()之前,所以这里设置state不会触发重新render。

这是唯一一个当服务器渲染时被调用的生命周期钩子,通常我们建议使用constructor()。

render()

被调用时,检查this.props,this.state,然后返回单个React元素,这个返回的React元素可以表示DOM节点,比如

,也可以表示自定义的组件, 比如

也可以返回null或者false,表明我们不想渲染,此时ReactDOM.findDOMNode(this)将返回null。

render()函数应该是纯函数,意味着不能修改组件的状态,它返回的是被调用时的结果,并且不能直接和浏览器交互。 如果需要和浏览器交互,需要在componentDidMount()或者其他生命周期中执行。如果shouldComponentUpdate()返回false,那么render将不执行。

componentDidMount()

当组件挂载之后被调用,需要得到DOM节点的操作应该在这里执行。

如果想从远程加载数据,也应在这里执行网络请求。

这里设置state,会触发重新渲染。

2. updating

  • componentWillReceiveProps()
  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()

componentWillReceiveProps(nextProps)

已经挂载的组件接收新的props之前会调用。

如果需要根据props的变化来更新状态,应该比较this.props和nextProps,并且在这里使用this.setState()执行状态转换。

即使props没有更新,这个方法也可能被调用,所以如果我们想处理变化,一定要比较当前props和下一个props。(当父组件造成子组件重新渲染时会遇到这种情况。)

在mounting期间,react不会用初始的props来调用这个方法。只有在一些组件的props可能更新的时候,才会调用这个方法。

执行this.setState不会触发这个事件。

shouldComponentUpdate(nextProps, nextState)

这个方法能够让react知道组件的输出是否因state或props的改变而受影响。默认就是当state一变化,就会重新渲染,大部分情况下我们使用默认的。

在rendering之前,当收到新的props或者state时,就会调用这个方法。当初始化渲染时,或者当使用forceUpdate()时,该方法不被调用。

返回false不能阻止子组件随他们的state重新渲染。如果返回false,那么componentWillUpdate(), render(), componentDidUpdate()不会被调用。

如果你发现一个组件在表示后很慢(????),可以考虑变成继承式的,从React.PureComponent继承,这意味着该方法此时是shallow prop and state comparision。

如果你想自己手写,那就可以比较this.props和nextprops,以及this.state和nextState,并返回false告诉react这个更新可以跳过。

componentWillUpdate(nextProps, nextState)

在收到新的props或者state后,rendering之前,调用该方法。

在这里可以做一些准备工作,来为更新做准备。

这个方法在初始渲染的时候不会被调用。

这里不能设置this.setState(),如果想根据props来更新state,应该在componentWillReceiveProps(nextProps)执行。

componentDidUpdate

当更新时被调用。

初始渲染的时候不被调用。

当组件更新后,应该在这里操作DOM。

网络请求适合放在这里,只要你比较了当前props和前一个props(当props没变化的时候,进行网络请求可能没有必要)。

3. unmounting

  • componentWillUnmount()

componentWillUnmount()

当卸载一个组件时或者销毁一个组件时,会执行。

可以在这里做一些清除工作,比如清除定时器,取消网络请求,清除在ComponentDidMount中创建的DOM元素。

4. 其他API

  • setState()
  • forceUpdate()

setState(updater, [callback])

认为setState是一个请求,而不是一个立即执行命令,会更好。因为为了更好的性能,react会延时它,并且在一个pass里同时更新好几个组件。所以react不能保证state的变化能立即生效。

setState()通常不立即更新组件。所以在componentDidUpdate或者setState的回调函数中去读取this.state,才能保证读取到的值最新的。

第一个参数是一个updater函数,

(prevState, props) => stateChange

prevState是前一个状态,它不应该直接被改变,相反,应该基于prevState和props建造一个新对象,从而展示变化。

比如,假设我们想增加一个值,

this.setState((prevState, props) => {
      return {counter: prevState.counter + props.step};
});

由updater函数接收的prevState和props是最新的。输出的updater将和prevState进行shallowly merged。

第二个参数是一个可选的回调函数,等setState完成并组建被重新渲染后才会执行。但是我们一般建议使用componentDidUpdate()来代替这个逻辑。

forceUpdate(callback)

component.forceUpdate(callback)

一般只有当state或者props变化时,组件才会重新渲染。但是如果我们想根据其他数据来渲染组件,就可以调用forceUpdate(),从而跳过shouldComponentUpdate()。这会触发子组件正常的生命周期,包括子组件的shouldComponentUpdate()方法。

一般要避免使用。

5. Class properties

  • defaultProps
  • displayName

defaultProps

设置默认属性,即当一个props是undefined时,才有用。如果是null,则不会采取默认值,还是null。

举个例子:

class CustomButton extends React.Component {
      // ...
}

CustomButton.defaultProps = {
      color: 'blue'
};

如果props.color没有提供,则默认就是blue:

render() {
    return <CustomButton /> ; // props.color will be set to blue
  }

如果props.color设置为null,则还是null:

render() {
    return <CustomButton color={null} /> ; // props.color will remain null
  }

displayName

用于debugging信息。JSX会自动设置这个值。

6. instance properties

  • props
  • state

props

this.props包含这个组件的调用者定义的props。

this.props.children是一个特殊的prop,通常是由子标签在JSX表达式中定义的,而不是在它自己的标签中。

state

不要直接修改this.state。

把它当做不可改变的。