原文连接:React Lifecycle Methods- how and when to use themjavascript
做者:Scott DomesFollow Front-End/Mobile Developer @ MuseFind.
翻译:johannlaijava
上名这个图片,就是 React 组件的生命周期,从造成 (pre-mounting)到销毁 (unmounting)的过程。react
React 的优雅之处就在于,它把复杂的 UI 分解成很小的部分。 咱们不只仅能够划分咱们的应用,并且咱们还能够定制咱们每个组件。canvas
经过组件的生命周期方法,咱们能够控制当UI的每一个微小部分渲染,更新,考虑从新渲染,而后彻底消失时会发生什么事情。网络
让咱们开始吧!ide
您的组件将很快就会出如今屏幕上面。这个大块的渲染功能与其全部精美的 JSX 同样,即将被调用。那你想作什么?函数
答案是... 可能不是不少。 可是 componentWillMount
的确用处不会太大。布局
关于 componentWillMount 的事情是,没有组件能够玩,因此你不能作任何涉及DOM的事情。(译者:由于还没渲染组件)性能
此外,自从您的组件的构造函数( constructor )被调用以来,没有任何变化,可是,不管如何,您应该在其中设置组件的默认配置。ui
export default calss Sidebar extends Component { constructor(props) { super(props) this.state = { analyticsOpen: false, requirementsOpen: false, barndInfoOpen: false } } }
如今您的组件处于默认位置,几乎全部的东西都应该由其他的组件代码来处理,而不须要额外的生命周期方法。
例外是只能在运行时完成的任何设置,说白了也就是链接到外部 API 。举个栗子,若是您的应用程序使用Firebase,则须要在应用程序首次挂载(mounting)时进行设置。
但关键是,这样的配置应该在应用程序的最高级别组件(根组件)。 这意味着99%的组件应该不能使用 componentWillMount
。
您可能会看到使用componentWillMount
的人启动AJAX调用来加载组件的数据。 千万不要这样作,咱们立刻就会聊到这个。
接下来,更有用的方法是:
最多见的用例: 您的根组件中的应用程序配置。
能够调用setState:不要。改用默认状态( default state )。
如今咱们在说话您的组件在那里,挂载了并准备好使用了。怎么办?
这里是您加载数据的位置。我会让 Tyler McGinnis 解释为何:
You can’t guarantee the AJAX request won’t resolve before the component mounts. If it did, that would mean that you’d be trying to setState on an unmounted component, which not only won’t work, but React will yell at you for. Doing AJAX in componentDidMount will guarantee that there’s a component to update.
您不能保证在组件挂载以前,AJAX请求将 resolve 。若是这样作,那意味着你会尝试在一个未挂载的组件上设置StState,这不只不会起做用,反而 React 会对你大喊大叫。在componentDidMount中执行AJAX将保证有一个要更新的组件。
ComponentDidMount
也能够在作不少你在没有组件的时候不能作的事情。 下面举几个栗子:
绘制您刚刚渲染的<canvas>元素
从元素集合初始化 masonry 网格布局
增长事件监听器
基本上,你能够在这里作任何刚刚由于没有 DOM 而不能作的设置,而且能够获取你所须要的所有数据。
最多见的用例: 启动AJAX
调用,以加载组件的数据。
能够调用setState:是的。
咱们的组成部分作得很好,忽然之间,一大堆新的 props
到达了,使到组件处于混乱状态。
颇有可能一些由父组件的componentDidMount
加载的数据终于到达,并被传递下来。
在咱们的组件对新的 props
进行任何操做以前,将调用componentWillReceiveProps
,并将下一props
做为参数。
<img alt="componentWillReceiveProps" src="https://cdn-images-1.medium.com/max/800/1*u3rXB0qKor51Qb_R1laPjw.png"
如今,咱们正在处于一个颇有趣的地方,咱们能够访问下一个 props
(经过nextProps)和咱们当前的 props
(经过this.props)。
下面这些是咱们在componentWillReceiveProps
中须要作的:
检查哪些props
会改变(使用componentWillReceiveProps的大警告 - 有时它什么也没有改变时被调用; React 只是想作一个检查)
若是props
会以重要的方式改变props
,就行事。
下面是一个例子。假设咱们在上面提到,咱们有一个 <canvas> 元素。假设咱们根据this.props.percent
绘制一个很好的圆形图形。
ps` ,若是百分比发生变化,咱们想从新绘制网格。如下是代码:
componentWillReceiveProps( nextProp ) { if(this.props.percent !== nextProps.percent) { this.setUpCirCle(nextProps.percent) } }
注意:在初始渲染时不调用 componentWillReceiveProps 。
个人意思是在技术上,组件正在接收props
,但没有任何旧的props
要比较,因此...不算。
最多见的用例:根据特定的props
,更改来触发状态(state)转换。
是否能够调用setState
: Yes
如今咱们的组件愈来愈紧张了。
咱们有新的props
。典型的React
教条说,当一个组件接收到新的props
或新的state
时,它应该更新。
可是咱们的组件有点焦虑,首先要求许可。
这是咱们所须要的 —— shouldComponentUpdate
方法,以 nextProps
为第一个参数,nextState
是第二个参数:
shouldComponentUpdate(nextProps, nextState) { return this.props.engagement !== nextProps,engagement || nextState.input !== this.state.input }
shouldComponentUpdate应该老是返回一个布尔值 —— 就像这个问题的答案
--> “我能够渲染吗?”
--> 是的,小组件,你能够去渲染。
默认状况下它老是返回true
。
可是,若是您担忧浪费渲染
其实,shouldComponentUpdate是提升性能的好地方。
我以这种方式写了一篇关于使用shouldComponentUpdate的文章 - 看看:
How to Benchmark React Components: The Quick and Dirty Guide
在这篇文章中,咱们谈论一个有不少fields的表格。问题是,当表从新渲染时,每一个字段也将从新渲染,速度很慢,效率很低。
ShouldComponentUpdate
容许咱们说:只有当所关心的props
的改变的时候才更新!
但请记住,若是您设置并忘记它可能会致使重大问题,由于您的React组件将没法正常更新。因此谨慎使用。
最多见的用例: 当您的组件 re-render
(从新渲染)时,彻底控制。
是否能够调用setState
: No
哇,什么过程如今咱们承诺更新。"但愿我在从新渲染以前先作任何事情?" 咱们的组件问。不,咱们说。中止打扰咱们。在整个MuseFind代码库中,咱们从不使用componentWillUpdate。在功能上,它基本上与componentWillReceiveProps
相同,除非你不容许调用this.setState
。
若是您正在使用shouldComponentUpdate
而且须要在props
更改时执行某些操做,那么componentWillUpdate
就会颇有意义。
最多见的用例: 在一个也有shouldComponentUpdate(但不能访问之前的props
)的组件上使用而不是componentWillReceiveProps
。
是否能够调用setState
: No
很棒!小组件!
在这里咱们能够和componentDidMount
作一样的事情 : 从新设置咱们的 masonry 布局,重绘咱们的canvas,等。
等等 - 咱们没有在componentWillReceiveProps
中重画咱们的canvas
吗?
是的咱们没有作。缘由是:在componentDidUpdate中,你不知道为何它更新。
所以,若是咱们的组件接收到的canvas
数量超过了与咱们的canvas
相关的props
,咱们不但愿每次更新时都会浪费时间重绘canvas
上面。
这并不意味着componentDidUpdate
没有用。要回到咱们的 masonry 布局示例,咱们要在DOM自身更新后从新排列网格,因此咱们使用componentDidUpdate
来完成。
componentDidUpdate() { this.createGrid() }
最多见的用例:更新DOM以响应prop
或state
更改。
是否能够调用setState
: Yes
几乎结束了~
你的组件将会消失。也许永远,这很伤心。
在它以前,它询问你是否有任何最后的请求。
在这里,您能够取消任何传出的网络请求,或删除与组件关联的全部事件监听器。
基本上,清理任何只涉及到有关的组件的哦事情,
当它走了,它应该彻底消失。
componentWillUnmount() { window.removeEventListen('resize', this,resizeListener) }
最多见的用例:清理组件中残留的残留物。
是否能够调用setState
: No
在理想的世界中,咱们不会使用生命周期方法。咱们全部的渲染问题都将经过state
和 prop
进行控制。
但它事实上并非一个理想的世界,有时您须要更准确地控制组件更新的方式和时间。
谨慎使用这些方法,并当心使用。我但愿这篇文章有助于阐明何时和如何使用生命周期方法。