react异步渲染组件_在预期异步渲染中重新使用React的组件生命周期

react异步渲染组件

by Alex Brown

通过亚历克斯布朗

在预期异步渲染时重新使用React的组件生命周期挂钩 (Revisiting use of React’s Component Life Cycle Hooks in Anticipation of Async Rendering)

If you’ve browsed the documentation, or kept an eye on the advice from the core React team, you’ve probably read that you shouldn’t handle subscriptions or side-effects in the constructor or componentWillMount.

如果您浏览了文档 ,或者关注了React核心团队的建议,那么您可能已经读过,不应在constructorcomponentWillMount处理订阅或副作用。

While the advice is clear, the reasoning behind these instructions hasn’t been greatly elaborated on, though not without reason. The brief explanation is that the implementation details of Fiber’s asynchronous rendering, motivating these instructions, aren’t entirely ironed out.

尽管建议很明确,但尽管并非没有道理 ,但并未对这些说明的理由进行详细说明。 简要的解释是,激发这些指令的Fiber异步呈现的实现细节并未完全消除。

Because Fiber’s async rendering isn’t yet enabled, ignoring some of the wisdom regarding life cycle usage might not have bitten you, yet. In the future, this might change, and that’s what we’re going to explore in this article.

由于尚未启用Fiber的异步渲染,因此忽略有关生命周期使用的某些知识可能尚未对您造成困扰。 将来,这可能会改变,这就是我们将在本文中探讨的内容。

澄清:光纤准备好了吗? (Clarification: Is Fiber ready?)

If Fiber’s async rendering isn’t ready to go, you might be wondering whether the team sold you a counterfeit countdown. Rest assured, this isn’t the case. Fiber’s new engine, or more specifically the reconciliation process, has been put into operation with React v16. With that said, we can’t change gears from synchronous render to prioritised renders just yet.

如果Fiber的异步渲染尚未准备就绪,您可能想知道团队是否向您出售了假冒倒计时 。 请放心,事实并非如此。 Fiber的新引擎,或更具体地说是对帐流程,已在React v16中投入运行。 话虽如此,我们还不能将齿轮从同步渲染更改为优先渲染。

使用生命周期将受到怎样的影响? (How will using life cycles be impacted?)

Conclusively, we don’t know until async rendering is set in stone. Otherwise the React team would have said as much. But we can draw some safe conclusions about handling subscriptions and side-effects. And that’s what we’ll explore.

最终,直到将异步渲染设置成石头,我们才知道。 否则,React团队会这么说。 但是我们可以得出有关处理订阅和副作用的一些安全结论。 这就是我们将要探索的。

For the sake of simplicity, here’s an example of subscribing to a media query list in the constructor, which presently will not cause us issues:

为了简单起见,下面是在构造函数中订阅媒体查询列表的示例, 目前不会导致我们出现问题:

Before async rendering is enabled, we don’t have any issues because we can make the following guarantees about the component:

在启用异步呈现之前,我们没有任何问题,因为我们可以对组件进行以下保证:

  1. The constructor will be synchronously followed by componentWillMount, if we opt to use it, and then render. Importantly, we won’t be interrupted before render. Because of this, we can further guarantee…

    如果我们选择使用constructor则在constructor将紧跟componentWillMount ,然后render重要的是,渲染之前我们不会被打断。 因此,我们可以进一步保证…

  2. If the component unmounts in the future, componentWillUnmountwill clean up the event listener (subscription) beforehand. This means that the window won’t retain a reference to the component’s handleMediaEvent method via the media query list, therefore allowing the unmounted component to be garbage collected and hence avoid a memory leak. Failing to clean this up once wouldn’t be a big deal, but a component re-mounting and adding more listeners could cause issues over the lifetime of the app.

    如果将来要卸载该组件, componentWillUnmount将事先清除事件侦听器(订阅)。 这意味着该window将不会通过媒体查询列表保留对组件的handleMediaEvent方法的引用,因此允许对已卸载的组件进行垃圾回收,从而避免内存泄漏。 一次不清理就不会有什么大不了,但是重新安装组件并添加更多侦听器可能会在应用程序的整个生命周期内引起问题。

There is one caveat: error boundaries. I’ll touch on that in a bit.
有一个警告:错误边界。 我会稍作讨论。
那么异步渲染会发生什么变化? (So what changes with async rendering?)

To get right to the point: many of your class component’s life cycle methods can fire more than once. This is because Fiber’s reconciliation process allows React to yield the work it is doing. Allowing the main thread to handle something that needs to be displayed urgently like animation. This can involve throwing away already completed work, potentially including invocations of the constructor, componentWillMount, render, componentWillUpdate, and componentWillReceiveProps.

正确地说:您的许多类组件的生命周期方法可以触发多次。 这是因为Fiber的对帐流程使React可以完成其正在做的工作。 允许主线程处理需要紧急显示的内容,例如动画。 这可能涉及丢弃已经完成的工作,可能包括调用constructorcomponentWillMountrendercomponentWillUpdatecomponentWillReceiveProps

But, componentDidUpdate and componentDidMount are only called after React has flushed changes to its host environment. Thus avoiding these issues. Cleanup or ‘tear down’ in componentWillUnmount should mirror the setup in componentDidMount. Helping to ensure a failure to call this hook will not be problematic.

但是,只有在React将其更改刷新到其主机环境后,才调用componentDidUpdatecomponentDidMount 。 从而避免了这些问题。 componentWillUnmount清理或“拆卸”应镜像componentWillUnmount的设置componentDidMount. 帮助确保调用此挂接失败不会有问题。

Thus, we need to be handling subscriptions and side-effects in componentDidMount. Side-effects taking place in the constructor and componentWillMount most often include network requests. They are especially troublesome to call multiple times when they result in mutations to our app’s back-end data stores.

因此,我们需要在componentDidMount处理订阅和副作用。 在constructorcomponentWillMount发生的副作用通常包括网络请求。 当它们导致我们的应用程序的后端数据存储发生更改时,多次调用特别麻烦。

One last note.

最后一点。

Like me, you might have assumed that React’s very first render is guaranteed to be always synchronous. But, this is not necessarily the case!

像我一样,您可能已经假设React的第一个渲染可以保证始终是同步的。 但是,不一定是这种情况!

Brian Vaughn (who is on the core React team) informed me that the current intention is for the first render to be sync by default, with optional async being opt-in. He added that a low-priority first render might be valuable if, for example, React’s host container isn’t yet ready. Obviously, this is more applicable where your HTML body consists of more than a single div for React to render to.

Brian Vaughn(React核心团队的负责人)告诉我,当前的意图是默认情况下首先同步第一个渲染,并选择启用可选异步。 他补充说,例如,如果React的宿主容器尚未准备好,那么低优先级的第一次渲染可能会很有价值。 显然,这在HTML主体由多个div以供React渲染的情况下更为适用。

For a visual checklist of what is safe to perform and where, see Brian’s gist.

有关可安全执行的操作以及在何处执行的直观检查表,请参阅Brian的要旨

componentWillMount作用是什么? (What purpose does componentWillMount serve?)

The use-case is very narrow. Developers often cite two desirable traits of componentWillMount. They are:

用例非常狭窄。 开发人员经常引用componentWillMount.两个理想特性componentWillMount. 他们是:

  1. setState can be called from componentWillMount, unlike the constructor.

    setState可以从componentWillMount调用,这与constructor不同。

  2. A setState in componentWillMount won’t cause two renders if it occurs synchronously, before render, unlike componentDidMount.

    setStatecomponentWillMount不会造成同步,如果它发生,前两渲染render ,不同于componentDidMount

Similarly, the reason componentWillMount was kept in the codebase originally, as Sebastian Markbåge explains in a proposal to deprecate componentWillMount, was to handle a side-effect that might be synchronous (if a local cache held the desired data) or asynchronous in the alternative. Today, as his demonstration code block conveys, getInitialState, es6 class constructors and es7 property initialisers cater to this purpose.

同样,正如SebastianMarkbåge在建议弃用componentWillMount的提案中解释的那样, componentWillMount最初保留在代码库中的原因是要处理可能是同步的(如果本地缓存保存了所需的数据)或异步的副作用。 今天,正如他的演示代码块所传达的那样, getInitialState ,es6类构造函数和es7属性初始化程序可以满足此目的。

With all this said, a read-only GET request initiated from componentWillMount can be useful. On a slow-to-render device, for example an average mobile, it’s possible to save a few hundred milliseconds by initiating the request here rather than componentDidMount. Of course, such a request should be idempotent/read-only as it may fire more than once.

综上所述,从componentWillMount发起的只读GET请求可能很有用。 在渲染速度较慢的设备(例如普通移动设备)上,可以通过在此处发起请求而不是componentDidMount来节省几百毫秒。 当然,这样的请求应该是幂等/只读的,因为它可能会触发多次。

When rendering on the server, componentWillMount is still the only life cycle method called other than the constructor, so it’s possible there are some use-cases there. Having not attempted server-side rendering myself, I can’t elaborate much on the topic.

在服务器上进行渲染时, componentWillMount仍然是除constructor之外唯一调用的生命周期方法,因此可能存在一些用例。 在没有尝试自己进行服务器端渲染的情况下,我无法就此主题进行详细说明。

那么这些警告仅在异步渲染生效后才有意义吗? (So are these warnings only relevant once async rendering is live?)

As Brian pointed out to me, not quite. Error boundaries, which went live with React v16, can also result in the invocation of componentWillMount and componentWillUpdate without a corresponding componentDidMount and componentDidUpdate!

正如布赖恩向我指出的那样。 React v16中存在的错误边界也可能导致在没有相应的componentWillMountcomponentWillUpdate情况下调用componentDidMountcomponentDidUpdate

还有其他需要警惕的变化吗? (Are there any other changes to be wary of?)

React recently initiated a RFC (Request For Comment) process, enabling the wider community to discuss ideas. Two of the first RFCs are from members of the React core team, discussing significant potential changes.

React最近启动了RFC(征求意见)流程,从而使更广泛的社区可以讨论想法。 第一个RFC中有两个来自React核心团队的成员,讨论了潜在的重大变化。

  1. Andrew Clark submitted an RFC about changes to the context API. This hopefully will ease some of the difficulty in getting around shouldComponentUpdate when attempting to broadcast state down the component tree. The RFC is here.

    Andrew Clark提交了有关上下文API更改的RFC。 希望这将缓解尝试在组件树中广播​​状态时绕过shouldComponentUpdate一些困难。 RFC在这里

  2. Brian submitted an RFC for async-safe, static life cycle hooks. This principally involves gradually deprecating componentWillMount, componentWillUpdate, and componentWillReceieveProps. Two new static hooks are proposed: prefetch and deriveStateFromProps. You can read more from the proposal here, and the RFC here. Hopefully this article provided you with some good insight as to why these changes are proposed :).

    Brian为异步安全的静态生命周期挂钩提交了RFC。 这主要涉及逐步弃用componentWillMountcomponentWillUpdatecomponentWillReceieveProps 。 提出了两个新的静态钩子: prefetchderiveStateFromProps 。 你可以阅读从提案更加这里 ,和RFC 这里 。 希望本文能为您提供一些很好的见解,说明为什么提出了这些更改:)。

  3. In the aforementioned proposal, Brian also teased a forthcoming RFC for a new SSR hook: componentDidServerRender, taking the place of componentWillMount on the server.

    在上述提议中,Brian还为新的SSR钩子准备了即将发布的RFC: componentDidServerRender ,代替了服务器上的componentWillMount

Keep in mind that these are early proposals!

请记住,这些都是早期建议!

关于作者 (About the author)

I’m an Australian developer located in Adelaide, passionate about both front and back-end development with JavaScript! I recently published my first open source library for React: React-MQL-Manager. Here’s a simple demo, integrating with React Router v4 for responsive routing!

我是一位位于阿德莱德的澳大利亚开发人员,对使用JavaScript进行前端和后端开发充满热情! 我最近为React发布了我的第一个开源库: React-MQL-Manager 。 这是一个简单的演示,与React Router v4集成以进行响应式路由!

I’m currently looking for my first front-end or full-stack position. You can reach me by email, or say hi to me over on twitter: @awebofbrown.

我目前正在寻找我的第一个前端或全栈位置。 您可以通过电子邮件与我联系,或者在Twitter上对我问好@awebofbrown

特别感谢 (Special Thanks)

A huge thank you to Brian Vaughn, of the React core team, for taking the time to read a draft of the article as well as making suggestions & corrections. In addition to working on React, Brian has authored some great open-source libraries such as React-Virtualized and JS-Search, as well as helping to answer community questions on forums like StackOverflow.

非常感谢React核心团队的Brian Vaughn花时间阅读本文草稿以及提出建议和更正。 除了致力于React,Brian还编写了一些很棒的开源库,例如React-VirtualizedJS-Search ,还帮助在诸如StackOverflow之类的论坛上回答社区问题。

翻译自: https://www.freecodecamp.org/news/how-to-safely-use-reacts-life-cycles-with-fiber-s-async-rendering-fd4469ebbd8f/

react异步渲染组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值