React组件生命周期

生命周期流程图简单如下:

组件让你把用户界面分成独立的,可重复使用的部分,并且将每个部分分开考虑。React.Component由...提供React


React.Component是一个抽象的基类,所以React.Component直接引用很少有意义。相反,您通常会将其子类化,并定义至少一个render()方法。

通常情况下,您可以将一个React组件定义为一个普通的JavaScript类

class Greeting extends React.Component{

render(){

return Hello,{this.props.name};

}

}

如果您还没有使用ES6,则可以使用该create-react-class模块。看看使用没有ES6的React来了解更多。

组件生命周期

每个组件都有几个“生命周期方法”,您可以在进程中的某些特定时间重写以运行代码。will在事件发生之前调用带有前缀的方法,并且did在事件发生之后调用带有前缀的方法。

安装

当创建一个组件的实例并将其插入到DOM中时,将调用这些方法:

constructor()

componentWillMount()

render()

componentDidMount()

更新

更新可以由道具或状态的更改引起。当一个组件被重新渲染时,这些方法被调用:

componentWillReceiveProps()

shouldComponentUpdate()

componentWillUpdate()

render()

componentDidUpdate()

卸载

从DOM中删除组件时调用此方法:

componentWillUnmount()

错误处理

在渲染期间,生命周期方法或任何子组件的构造函数中发生错误时调用此方法。

componentDidCatch()

其他API

每个组件还提供一些其他API:

setState()

forceUpdate()

类属性

defaultProps

displayName

实例属性

props

state

参考

render()

render()

该render()方法是必需的。

被调用时,应该检查this.props并this.state返回以下类型之一:

React元素。通常通过JSX创建。元素可以是本地DOM组件()的表示,也可以是用户定义的组合组件()。

字符串和数字。这些在DOM中呈现为文本节点。

门户网站。创建于ReactDOM.createPortal

null。不渲染任何东西。

布尔人。什么都不渲染。(主要存在支持return test && 模式,其中test是布尔值。)

当返回null或false,ReactDOM.findDOMNode(this)将返回null。

该render()函数应该是纯粹的,意味着它不会修改组件状态,每次调用时都会返回相同的结果,并且不会直接与浏览器交互。如果您需要与浏览器进行交互,请componentDidMount()改为使用其他生命周期方法。保持render()纯粹使组件更容易思考。

注意

render()如果shouldComponentUpdate()返回false,则不会被调用。

片段

您也可以render()使用数组返回多个项目:

render(){return[First item,Second item,Third item,];}

注意:

不要忘记添加键到片段中的元素,以避免重要的警告。

constructor()

constructor(props)

React组件的构造函数在挂载之前被调用。在实现React.Component子类的构造函数时,应该super(props)在任何其他语句之前调用。否则,this.props会在构造函数中定义,这可能会导致错误。

避免在构造函数中引入任何副作用或订阅。对于这些用例,请componentDidMount()改为使用。

构造函数是初始化状态的正确位置。要做到这一点,只需分配一个对象this.state; 不要尝试setState()从构造函数调用。构造函数也经常用于将事件处理程序绑定到类实例。

如果您不初始化状态,并且不绑定方法,则不需要为React组件实现构造函数。

在极少数情况下,可以根据道具初始化状​​态。这有效地“叉”的道具,并设置与初始道具的状态。下面是一个有效的React.Component子类构造函数的例子:

constructor(props){super(props);this.state={color:props.initialColor};}

小心这种模式,因为国家将不会更新任何道具。而不是将道具同步到状态,而是经常想要提升状态

如果你使用他们的状态“叉”道具,你也可能想要执行,componentWillReceiveProps(nextProps)以保持状态与他们最新。但是提升状态通常更容易,并且更少出现错误。

componentWillMount()

componentWillMount()

componentWillMount()在安装发生之前立即被调用。它之前被调用render(),因此setState()在这个方法中同步调用不会触发额外的渲染。一般来说,我们推荐使用constructor()。

避免在此方法中引入任何副作用或订阅。对于这些用例,请componentDidMount()改为使用。

这是在服务器渲染上调用的唯一的生命周期钩子。

componentDidMount()

componentDidMount()

componentDidMount()在组件被装载后立即被调用。需要DOM节点的初始化应该在这里。如果您需要从远程端点加载数据,这是一个实例化网络请求的好地方。

这种方法是设置任何订阅的好地方。如果你这样做,不要忘记退订componentWillUnmount()。

调用setState()这个方法会触发一个额外的渲染,但在浏览器更新屏幕之前会发生。这保证即使render()在这种情况下将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,因为这通常会导致性能问题。但是,当需要在渲染依赖于其大小或位置的东西之前测量DOM节点时,可能需要类似于模态和工具提示的情况。

componentWillReceiveProps()

componentWillReceiveProps(nextProps)

componentWillReceiveProps()在安装的组件接收新的道具之前被调用。如果您需要在响应更新状态托变化(例如,复位),你可以比较this.props和nextProps和执行使用状态转换this.setState()在此方法。

请注意,即使道具尚未更改,React也可能会调用此方法,因此如果您只想处理更改,请务必比较当前值和下一个值。父组件导致组件重新呈现时,可能会发生这种情况。

componentWillReceiveProps()在安装过程中,反应不会与初始道具呼叫。只有在组件的某些道具可能更新时才会调用这个方法。调用this.setState()通常不会触发componentWillReceiveProps()。

shouldComponentUpdate()

shouldComponentUpdate(nextProps,nextState)

使用shouldComponentUpdate()让阵营知道,如果一个组件的输出不会受到州或道具的电流变化。默认行为是在每次状态更改时重新呈现,在绝大多数情况下,您应该依靠默认行为。

shouldComponentUpdate()在渲染新的道具或状态时被调用。默认为true。此方法不用于初始渲染或何时forceUpdate()使用。

返回false不会阻止子组件在状态更改时重新呈现。

目前,如果shouldComponentUpdate()回报false,然后componentWillUpdate()render()componentDidUpdate()将不会被调用。请注意,将来React可能会被shouldComponentUpdate()视为提示而不是严格的指令,并且返回false可能仍会导致组件的重新呈现。

如果确定特定组件在分析后缓慢,则可以将其更改为从具有较浅支撑和状态比较的React.PureComponent哪些实现中继承shouldComponentUpdate()。如果你确信你想用手写,你可以比较this.props,nextProps并this.state与nextState返回false告诉React更新可以跳过。

我们不建议这样做深平等检查或使用JSON.stringify()在shouldComponentUpdate()。这是非常低效的,会损害性能。

componentWillUpdate()

componentWillUpdate(nextProps,nextState)

componentWillUpdate()在渲染新的道具或状态时立即被调用。使用这个机会在更新发生之前执行准备工作。这个方法不是为初始渲染调用的。

请注意,你不能this.setState()在这里打电话; 你也不应该做任何其他的事情(比如派遣一个Redux动作),在componentWillUpdate()返回之前触发一个React组件的更新。

如果您需要更新state以响应props更改,请componentWillReceiveProps()改为使用。

注意

componentWillUpdate()如果shouldComponentUpdate()返回false,则不会被调用。

componentDidUpdate()

componentDidUpdate(prevProps,prevState)

componentDidUpdate()在更新发生后立即被调用。这个方法不是为初始渲染调用的。

当组件更新时,可以使用这个机会来操作DOM。只要你将目前的道具与以前的道具进行比较,这也是一个很好的做网络请求的地方(例如,如果道具没有改变,可能不需要网络请求)。

注意

componentDidUpdate()如果shouldComponentUpdate()返回false,则不会被调用。

componentWillUnmount()

componentWillUnmount()

componentWillUnmount()在组件被卸载并销毁之前立即被调用。在这个方法中执行任何必要的清理,例如使定时器无效,取消网络请求,或者清理在其中创建的任何订阅componentDidMount()。

componentDidCatch()

componentDidCatch(error,info)

错误边界是React组件,可以在其子组件树中的任何位置捕获JavaScript错误,记录这些错误,并显示备用UI而不是崩溃的组件树。错误边界在渲染,生命周期方法以及整个树下的构造函数中捕获错误。

如果一个类组件定义了这个生命周期方法,它将成为一个错误边界。调用setState()它可以在下面的树中捕获未处理的JavaScript错误,并显示一个后备UI。只能使用错误边界从意外的异常中恢复; 不要试图将它们用于控制流程。

有关更多详细信息,请参阅React 16中的错误处理

注意

错误边界只会捕获树中下面的组件中的错误。错误边界本身不能捕获错误。

setState()

setState(updater[,callback])

setState()将更改排入组件状态,并告诉React该组件及其子组件需要使用更新的状态重新呈现。这是用来更新用户界面以响应事件处理程序和服务器响应的主要方法。

将其setState()看作是一个请求,而不是一个立即的命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后一次更新几个组件。React不保证立即应用状态更改。

setState()并不总是立即更新组件。它可能会批处理或推迟更新,直到更晚。这使得阅读this.state正确后,setState()可能会陷入困境。相反,使用componentDidUpdate或setState回调(setState(updater, callback)),其中任何一个保证在应用更新后触发。如果您需要根据以前的状态设置状态,请阅读updater下面的参数。

setState()总是会导致重新呈现,除非shouldComponentUpdate()得到回报false。如果正在使用可变对象并且无法实现条件呈现逻辑shouldComponentUpdate(),则setState()仅在新状态与先前状态不同时调用将避免不必要的重新呈现。

第一个参数是updater带签名的函数:

(prevState,props)=>stateChange

prevState是对以前的状态的参考。它不应该直接变异。相反,应根据来自prevState和的输入构建新对象来表示更改props。例如,假设我们想通过以下方式增加一个状态值props.step:

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

二者prevState并props通过更新功能接收保证是向上的更新。更新程序的输出与浅层合并prevState。

第二个参数setState()是一个可执行的回调函数,将被执行一次setState完成,并重新渲染组件。通常我们推荐使用componentDidUpdate()这样的逻辑来代替。

你可以选择传递一个对象作为第一个参数来setState()代替函数:

setState(stateChange[,callback])

这会执行stateChange到新状态的浅层合并,例如调整购物车项目数量:

this.setState({quantity:2})

这种形式setState()也是异步的,并且在同一个周期内的多个调用可以一起进行批处理。例如,如果您尝试在同一个周期内多次增加一个项目数量,那么将导致等同于:

Object.assign(previousState,{quantity:state.quantity+1},{quantity:state.quantity+1},...)

随后的调用将覆盖同一周期中先前调用的值,因此数量只会增加一次。如果下一个状态取决于之前的状态,我们建议使用更新函数形式,而不是:

this.setState((prevState)=>{return{quantity:prevState.quantity+1};});

有关更多详细信息,请参阅州和生命周期指南

forceUpdate()

component.forceUpdate(callback)

默认情况下,当组件的状态或者道具改变时,你的组件将重新渲染。如果你的render()方法依赖于其他数据,你可以通过调用告诉React组件需要重新渲染forceUpdate()。

调用forceUpdate()将导致render()在组件上调用,跳过shouldComponentUpdate()。这将触发子组件的正常生命周期方法,包括shouldComponentUpdate()每个子组件的方法。如果标记更改,React将只会更新DOM。

通常情况下,你应该尽量避免所有的使用forceUpdate()和只读this.props和this.state中render()。

类属性

defaultProps

defaultProps可以被定义为组件类本身的一个属性,来设置该类的默认道具。这用于未定义的道具,但不适用于null道具。例如:

classCustomButtonextendsReact.Component{// ...}CustomButton.defaultProps={color:'blue'};

如果props.color没有提供,它将被默认设置为'blue':

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

如果props.color设置为空,它将保持为空:

render(){return;// props.color will remain null}

displayName

该displayName字符串用于调试消息。通常,您不需要明确设置它,因为它是从定义组件的函数或类的名称推断出来的。如果要为调试目的显示不同的名称,或者要创建高阶组件,则可能需要显式设置它,有关详细信息,请参阅包装显示名称以进行简单调试

实例属性

props

this.props包含由该组件的调用者定义的道具。请参阅组件和道具以了解道具的介绍。

特别是,它this.props.children是一个特殊的道具,通常由JSX表达式中的子标签定义,而不是标签本身。

state

状态包含特定于此组件的数据,可能随时间而改变。状态是用户定义的,它应该是一个普通的JavaScript对象。

如果你不使用它render(),它不应该在这个状态。例如,您可以将计时器ID直接放在实例上。

有关状态的更多信息,请参阅状态和生命周期

不要this.state直接变异,因为setState()之后的调用可能会取代你所做的变异。把this.state它看作是不可改变的。



visio下载地址:react组件生命周期


推荐阅读更多精彩内容