[译]React 的生命周期的使用场景

[译]React 的生命周期的使用场景

clipboard.png

原文链接:React Lifecycle Methods- how and when to use them

作者:Scott DomesFollow Front-End/Mobile Developer @ MuseFind.
翻译:johannlai

上名这个图片,就是 React 组件的生命周期,从形成 (pre-mounting)到销毁 (unmounting)的过程。

React 的优雅之处就在于,它把复杂的 UI 分解成很小的部分。 我们不仅仅可以划分我们的应用,而且我们还可以定制我们每一个组件。

通过组件的生命周期方法,我们可以控制当UI的每个微小部分渲染,更新,考虑重新渲染,然后完全消失时会发生什么事情。

让我们开始吧!

componentWillMount

您的组件将很快就会出现在屏幕上面。这个大块的渲染功能与其所有精美的 JSX 一样,即将被调用。那你想做什么?

答案是... 可能不是很多。 但是 componentWillMount 的确用处不会太大。

关于 componentWillMount 的事情是,没有组件可以玩,所以你不能做任何涉及DOM的事情。(译者:因为还没渲染组件)

此外,自从您的组件的构造函数( constructor )被调用以来,没有任何变化,但是,无论如何,您应该在其中设置组件的默认配置。

  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 )。

componentDidMount

现在我们在说话您的组件在那里,挂载了并准备好使用了。怎么办?

这里是您加载数据的位置。我会让 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:是的。

componentWillReceiveProps

我们的组成部分做得很好,突然之间,一大堆新的 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

shouldComponentUpdate

现在我们的组件越来越紧张了。

我们有新的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

componentWillUpdate

哇,什么过程现在我们承诺更新。"希望我在重新渲染之前先做任何事情?" 我们的组件问。不,我们说。停止打扰我们。在整个MuseFind代码库中,我们从不使用componentWillUpdate。在功能上,它基本上与componentWillReceiveProps相同,除非你不允许调用this.setState

如果您正在使用shouldComponentUpdate 并且需要在props更改时执行某些操作,那么componentWillUpdate就会很有意义。

最常见的用例: 在一个也有shouldComponentUpdate(但不能访问以前的props)的组件上使用而不是componentWillReceiveProps

是否可以调用setState: No

componentDidUpdate

很棒!小组件!

在这里我们可以和componentDidMount做同样的事情 : 重新设置我们的 masonry 布局,重绘我们的canvas,等。

等等 - 我们没有在componentWillReceiveProps中重画我们的canvas吗?

是的我们没有做。原因是:在componentDidUpdate中,你不知道为什么它更新。

因此,如果我们的组件接收到的canvas数量超过了与我们的canvas相关的props,我们不希望每次更新时都会浪费时间重绘canvas上面。

这并不意味着componentDidUpdate没有用。要回到我们的 masonry 布局示例,我们要在DOM自身更新后重新排列网格,所以我们使用componentDidUpdate来完成。

componentDidUpdate() {
  this.createGrid()
}

最常见的用例:更新DOM以响应propstate更改。
是否可以调用setState: Yes

componentWillUnmount

几乎结束了~

你的组件将会消失。也许永远,这很伤心。

在它之前,它询问你是否有任何最后的请求。

在这里,您可以取消任何传出的网络请求,或删除与组件关联的所有事件监听器。

基本上,清理任何只涉及到有关的组件的哦事情,
当它走了,它应该完全消失。

componentWillUnmount() {
  window.removeEventListen('resize', this,resizeListener)
}

最常见的用例:清理组件中残留的残留物。
是否可以调用setState: No

总结

在理想的世界中,我们不会使用生命周期方法。我们所有的渲染问题都将通过stateprop进行控制。

但它事实上并不是一个理想的世界,有时您需要更准确地控制组件更新的方式和时间。

谨慎使用这些方法,并小心使用。我希望这篇文章有助于阐明什么时候和如何使用生命周期方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值