组件的生命周期方法分以下三个阶段。
Mounting
当创建组件的实例并将其插入到DOM中时,将调用这些方法:
constructor()
componentWillMount()
render()
componentDidMount()
Updating
更新可能是props或state的改变引起的。 当重新渲染组件时,将调用这些方法:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
Unmounting
当组件从dom中移除时调用:
componentWillUnmount()
找来一张图:
以下详细讲解下每个方法(翻译来的)。
render()
render()方法是必需的。调用时,应该检查this.props和this.state并返回一个React元素。 例如<div />或您自己定义的另一个复合组件。
您也可以返回null
或false
表示您不希望任何呈现。 返回null
或false
时,ReactDOM.findDOMNode(this)将返回null
。
render()函数应该是纯函数,这意味着它不会修改组件状态,每次调用它都会返回相同的结果,并且它不会直接与浏览器交互。 如果需要与浏览器交互,请在componentDidMount()或其他生命周期方法中执行工作。 保持render()纯粹使组件更容易思考。
如果shouldComponentUpdate()返回false,则不会调用render()。
constructor(props)
组件构造函数会在组件装载到页面之前调用。在实现React.Component子类的构造函数时,您应该在任何其他语句之前调用super(props)
。 否则,this.props将在构造函数中未定义,这可能会导致错误。
构造函数是初始化状态的正确位置。 如果不初始化状态并且不绑定方法,则不需要为您的React组件实现一个构造函数。
可以根据props来初始化状态。 这是一个有效的React.Component子类构造函数的示例:
constructor(props) {
super(props);
this.state = {
color: props.initialColor
};
}
小心这种模式,因为状态不会随着任何props更新而更新。 你通常不想将props同步到state,而是要提升状态。如果您通过使用props更新状态,您可能还需要实现componentWillReceiveProps(nextProps)来保持状态与其最新状态。 但是提升状态往往比较容易,而且不容易出错。
componentWillMount()
在元素装载发生之前会调用componentWillMount()。
避免在此方法中引入任何副作用或订阅。
它在render()之前被调用,因此在该方法中同步设置状态不会触发重新呈现。 这是在服务器渲染上调用的唯一生命周期钩子。 一般来说,建议使用constructor()。
componentDidMount()
在元素装载发生之后会调用componentDidMount()。
DOM节点的初始化应该在这里。 如果需要从远程端点加载数据,这是实例化网络请求的好地方。 此方法中的设置状态将触发重新渲染。
componentWillReceiveProps(nextProps)
当组件接收到一个新的props时该方法触发. 如果需要更新状态以响应更改(例如,要重置它),则可以比较this.props和nextProps,并使用此方法中的this.setState()执行状态转换。
请注意,即使props没有改变,React也可以调用此方法,因此如果只想处理更改,请确保比较当前值和下一个值。 当父组件使您的组件重新呈现时,可能会发生这种情况。
在装载过程中,React不会使用初始props调用componentWillReceiveProps。 只会在某些组件的props更新时才会调用此方法。 调用this.setState通常不会触发componentWillReceiveProps。
shouldComponentUpdate(nextProps, nextState)
使用shouldComponentUpdate()让React知道组件的输出是否不受当前state或props的更改的影响。默认行为是在每个状态更改时重新呈现,而在绝大多数情况下,您应该依赖于默认行为。
在接收到新的props或state时,将在渲染之前调用shouldComponentUpdate()。默认为true。
对于初始渲染,或者当使用forceUpdate()时,不调用此方法。
返回false不会阻止子组件在状态更改时重新渲染。
目前,如果shouldComponentUpdate()返回false,那么将不会调用componentWillUpdate(),render()和componentDidUpdate()。请注意,在将来,React可以将shouldComponentUpdate()作为一个提示而不是一个strict指令,并返回false仍然可能导致组件的重新呈现。
如果在分析后确定特定组件较慢,则可以将其更改为继承自实现shouldComponentUpdate()的React.PureComponent
,对props和state进行浅比较。如果您有信心要手动编写,可以将this.props与nextProps和this.state与nextState进行比较,并返回false以告知React可以跳过更新。
componentWillUpdate(nextProps, nextState)
会在render之前触发,一个新的props和state会被做为参数传进来 。使用此作为在更新发生之前进行准备的机会。 初始化渲染不会调用此方法。
请注意,您不能在此处调用this.setState()。 如果需要更新状态以响应更改,请改用componentWillReceiveProps()。
如果shouldComponentUpdate()返回false,则不会调用componentWillUpdate()。
componentDidUpdate(prevProps, prevState)
会在更新发生后立即执行. 初始化渲染不会调用此方法。
当组件更新时,使用它作为在DOM上操作的机会。 只要您将当前props与以前的props进行比较。
这也是网络请求的好地方(如果props没有改变,则网络请求可能不是必需的)。
componentWillUnmount()
在组件被卸载并销毁之前,会立即调用此方法。 在此方法中执行任何必要的清理,例如使定时器无效,取消网络请求或清除DOM元素
(在componentDidMount中创建的任何DOM元素)。
setState(updater, [callback])
setState()将对组件状态的更改插入队列,并告诉React,该组件及其子组件需要更新状态重新呈现。这是用于更新用户界面以响应事件处理程序和服务器响应的主要方法。
将setState()作为请求而不是立即命令来更新组件。为了更好的感知性能,React可能会延迟它,然后在单次通过中更新多个组件。 React不能保证立即应用状态更改。
setState()并不总是立即更新组件。它可能会批量或延迟更新直。这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。最好的方法是使用componentDidUpdate或setState回调(setState(updater,callback)),其中的任何一个都会在应用更新后都被触发。
setState()将永远导致重新渲染,除非shouldComponentUpdate()返回false。
第一个参数是具有签名的更新功能:
(prevState,props)=> stateChange
prevState是对以前状态的引用。不应该直接突变。相反,应该根据prevState和props的输入构建一个新对象来表示更改。例如,假设我们想通过props.step来增加状态值:
this.setState((prevState,props)=> {
return {counter:prevState.counter + props.step};
});
updater功能接收到的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},
...
)
后续呼叫将覆盖同一周期中先前呼叫的值,因此数量只会增加一次。如果下一个状态取决于以前的状态,我们建议使用updater函数形式:
this.setState((prevState)=> {
return {counter:prevState.quantity + 1};
});
forceUpdate (callback)
默认情况下,当您的组件的state或props更改时,您的组件将重新呈现。如果您的render()方法依赖于某些其他数据,您可以通过调用forceUpdate()来告诉React该组件需要重新呈现。
调用forceUpdate()将导致在组件上调用render(),跳过shouldComponentUpdate()。这将触发子组件的正常生命周期方法,包括每个子组件的shouldComponentUpdate()方法。如果标记更改,则React仍将仅更新DOM。
通常你应该尽量避免使用forceUpdate(),只能从render.()中的this.props和this.state读取。