[译] React v16.9.0 and the Roadmap Update

1,108

原文地址

今天我们正式发布了 React 16.9. 这次更新包含了一些新的特性,bug的修复,还通过增加一些废弃 api 的警告去帮助开发者更好的为新的大版本迭代做准备

移除生命周期中一些不安全的方法

在过去的一年, 我们宣布重新命名不安全的生命周期方法:

  • componentWillMountUNSAFE_componentWillMount
  • componentWillReceivePropsUNSAFE_componentWillReceiveProps
  • componentWillUpdateUNSAFE_componentWillUpdate

React 16.9 不包含破坏性的更改, 这些老的 api 名称 任然可以在这个版本中使用。 但是当你使用这些方法的时候,会看到一些警告:

Warning: componentWillMount has been renamed, and is not recommended for use.

正如警告所示,对于这些不安全的方法,通常有更好的方法 去替换. 然而,如果你现在没有时间去迁移跟测试这些使用了不安全方法的组件,我们建议使用 "codemod" 来自动重新命名:

cd your_project
npx react-codemod rename-unsafe-lifecycles

(注意!这里使用的是 npx, 不是 npm. ) 运行 codemon 将会这样替换老的名字,例如 componentWillMount 会被替换成 UNSAFE_componentWillMount

Codemod in action
UNSAFE_componentWillMount 这样的新名称将继续在 React 16.9 跟 React 17.x 中正常工作。然而,这些带有 UNSAFE_ 前缀方法的组件会在代码 review 跟 debug 模式快速被发现。(如果你愿意,你可以在严格模式下阻止这些方法出现在你的组件中)

Note

了解更多关于我们的版本控制策略和对稳定性的承诺。.

Deprecating javascript: URLs {#deprecating-javascript-urls}

因为很容易在 <a href> 中包含了一个没有处理的链接,从而产生安全漏洞, 所以以 javascript: 开头的 URLS  是一个危险的可以被攻击的点,

const userProfile = {
  website: "javascript: alert('you got hacked')",
};
// This will now warn:
<a href={userProfile.website}>Profile</a>

尽管在 React 16.9中, 这种模式依然可以正常运行, 但是会有一个警告信息. 如果你在代码中使用了 javascript: URLs,尽量使用 React 的时间处理方法。(如果实在没办法,非要使用javascript:URLS,可以使用 dangerouslySetInnerHTML 来规避问题,但是非常不鼓励这种行为,这样经常会导致一些安全问题)

在未来的大版本中, 如果遇到了 javascript: URL,React 会直接抛出一个异常.

Deprecating "Factory" Components {#deprecating-factory-components}

在使用 Babel 编译 JavaScript classes 变得流行之前,React支持一个 factory 组件,该组件返回一个带有 render 方法的对象:

function FactoryComponent() {
  return { render() { return <div />; } }
}

这种模式让人很迷糊,因为它看起来像是一个 function component, 但是它又不是。(一个 function component 只会返回上述例子中的<div/>

这种模式基本上没有大范围的使用,支持这种模式反而导致 React 体积变得更大,运行的更慢。所以我们再 16.9 版本中废弃了这种模式,并且在使用这个模式的地方增加了一个警告信息,如果你必须要使用这种模式,增加一行 FactoryComponent.prototype = React.Component.prototype 可以帮助你正常的运行,或者你可以将其更换为 class component 或者 function component

我们不认为大多数代码库会受此影响.

New Features {#new-features}

Async act() for Testing {#async-act-for-testing}

React 16.8 介绍了一个新的单元测试方法act()去帮助你结合浏览器的行为更好的写测试。 举个例子,在单个 act() 中多个 state 更新会被批量处理,这与 React 在浏览器中处理的工作模式一致,并且有助于你的组件为React接下来的批量更新做准备。 然而, 在 16.8 act() 只支持同步的方法,有时候,你可能在测试中看到过这样的警告,但却不能轻易地修复它:

An update to SomeComponent inside a test was not wrapped in act(...).

在 React 16.9, act() 不仅支持异步函数, 而且支持使用 await:

await act(async () => {
  // ...
});

这解决了之前不能使用 act() 的情况,比如当状态更新发生在一个异步函数中。因此你现在可以修复之前遗留的 act() 警告了。

我们听说这里没有足够的信息去教大家怎么使用 act() 去写测试。新的测试指南描述了一些常用的场景,以及 act() 如何帮助你写好测试。在这些例子中,我们使用了 vanilla DOM APIs, 但是你也可以使用 React Testing Library 去减少一些 boilerplate code。它的许多方法在内部使用了 act()

如果你再使用 act() 的过程中遇到了什么问题,都可以将错误信息的堆栈告知我们,我们将尽力提供帮助

Performance Measurements with <React.Profiler> {#performance-measurements-with-reactprofiler}

React 16.5 的版本中,我们介绍了一个新的 React 性能分析器的开发工具去帮助开发者找到自己项目的性能瓶颈。**在 React 16.9版本中,我们还增加了<React.Profiler>来以编码的方式去收集跟测量性能。我们预计在大多数的小型应用中并不需要它,但是较大的项目中,随着时间去跟踪性能跟回归将会变得很方便

<Profiler> 测量 React App 渲染的频率跟渲染的成本。它的目的是去识别项目中运行的很慢的并且可能被优化的部分,优化的方案比如memoization

可以在任意的 React tree 中添加 <Profiler> 去测量这部分内容的渲染频率跟消耗。它接受两个参数,一个 id(string),一个 onRender callbackonRender 会在React 树中任意一个组件执行commit更新操作时候调用

render(
  <Profiler id="application" onRender={onRenderCallback}>
    <App>
      <Navigation {...props} />
      <Main {...props} />
    </App>
  </Profiler>
);

要了解有关 Profiler 和传递给 onRender 回调的参数的更多信息,请查看 Profiler文档

Note: Profiling 会增加额外的开销,所以在 **production 模式下是被禁止的**

如果想要在 production 模式下进行分析, React 提供了一种特殊的 production build 来 开启性能分析 想查看如何使用这种构建方式请查看fb.me/react-profi….

Notable Bugfixes {#notable-bugfixes}

这个版本包含了一些其他值得注意的改进:

我们感谢所有帮助解决这些和其他问题的贡献者。您可以在下面找到完整的变更日志。

An Update to the Roadmap {#an-update-to-the-roadmap}

2018年11月, 我们发布 React 16.x 版本的进军路线

  • A minor 16.x release with React Hooks (past estimate: Q1 2019)
  • A minor 16.x release with Concurrent Mode (past estimate: Q2 2019)
  • A minor 16.x release with Suspense for Data Fetching (past estimate: mid 2019)

这些估计太乐观了,我们需要调整。(排期太紧,RD要求延期😭)

tldr: 我们按时完成了 Hooks,但我们正在将Concurrent Mode和Suspense for Data Fetching重新组合成一个我们打算在今年晚些时候发布的版本。 在二月份,我们发布的 16.8 版本中包含了 React Hooks,并且在一个月以后 React Native 也完成了支持。但是,我们低估了这个版本的后续工作,包括lint规则、开发工具、示例和更多文档。这使时间轴提前了几个月。 现在 React Hooks 已经正式推出,现在 Concurrent ModeSuspense for Data Fetching 的工作已经全面展开,现在 Facebook 的新网站就是基于上面这些功能的基础上开发的。在项目中实践有助于在影响开源用户使用前解决很多问题。其中一些问题的修复跟这些特性的内部重新设计也导致了延期。

有了这种新的理解,这就是我们计划下一步做的事情

One Release Instead of Two {#one-release-instead-of-two}

Concurrent ModeSuspense 已经在为在新开发 Facebook 网站提供支持了,所以我们有信心他们在技术上接近稳定状态。 我们现在也更好地了解了它们为开源采用做好准备之前的具体步骤。

最初我们认为我们会将Concurrent Mode和Suspense for Data Fetching分成两个版本。 我们发现这种排序很难解释,因为这些特征与我们最初想到的相关性更大。 因此,我们计划在单个组合版本中发布对Concurrent Mode和Suspense for Data Fetching的支持。

我们不想再次过多地承诺发布日期,鉴于我们在生产代码中依赖于它们,我们希望今年能够提供16.x版本,并为其提供选择支持。

An Update on Data Fetching {#an-update-on-data-fetching}

尽管 React 不会对如何获取数据发表意见,但数据提取的Suspense的第一个版本可能会专注于与固定数据提取库集成。举个例子,在 Facebook 我们正在使用即将推出的集成了 Suspense 的Relay API。

在第一个版本中,我们不打算关注我们在早期演示中使用的临时“触发HTTP请求”解决方案(也称为“React Cache”)。 但是,我们希望我们和React社区将在首次发布后的几个月内探索该空间。

An Update on Server Rendering {#an-update-on-server-rendering}

我们已经开始研究 Suspense-capable在服务端的渲染,但是我们并不期望它能在并发模式的初始版本中使用。但是,此版本将提供一个临时解决方案,允许现有服务器呈现器立即为Suspense回退发出HTML,然后在客户端上呈现其真实内容。 这是我们目前在Facebook上使用的解决方案,直到流式渲染器准备就绪。

Why Is It Taking So Long? {#why-is-it-taking-so-long}

We've shipped the individual pieces leading up to Concurrent Mode as they became stable, including new context API, lazy loading with Suspense, and Hooks. We are also eager to release the other missing parts, but trying them at scale is an important part of the process. The honest answer is that it just took more work than we expected when we started. As always, we appreciate your questions and feedback on Twitter and in our issue tracker.