react生命周期

组件的生命周期方法分以下三个阶段。

Mounting
当创建组件的实例并将其插入到DOM中时,将调用这些方法:
constructor()
componentWillMount()
render()
componentDidMount()

Updating
更新可能是props或state的改变引起的。 当重新渲染组件时,将调用这些方法:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()

Unmounting
当组件从dom中移除时调用:
componentWillUnmount()

找来一张图:


react-lifecycle.png

以下详细讲解下每个方法(翻译来的)。

render()
render()方法是必需的。调用时,应该检查this.props和this.state并返回一个React元素。 例如<div />或您自己定义的另一个复合组件。
您也可以返回nullfalse表示您不希望任何呈现。 返回nullfalse时,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读取。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 好比我们人除了短暂的生与死那一瞬之外,生命中剩下的时间都用在了每天活着的状态,对于React中的组件来讲,占其总生...
    YeLqgd阅读 10,288评论 0 7
  • 1.组件挂载和卸载时 componentWillMount在render方法之前执行,只会在组件初始化时运行一次,...
    星月西阅读 975评论 0 0
  • 译自 React Component Lifecycle 每个组件都有若干生命周期函数。如函数名称所示,带有wil...
    KrisLeeSH阅读 534评论 0 0
  • 又是一个老生常谈的内容,从ES6起已经开始使用class的方式去创建组件,这种创建方式上的变化也带来了写法和方法上...
    殷灬商阅读 435评论 0 1
  • 组件的生命周期 组件会经过三个过程: 装载过程(Mount),也就是把组件爱你第一次在DOM树中渲染的过程; 更新...
    Kris_lee阅读 467评论 0 1