今天我们发布了React 16.9。它包含了一些新的功能、错误修复和新的废弃警告,以帮助为未来的主要版本做准备。
新删减的内容
重命名不安全的生命周期方法
一年多前,我们宣布不安全的生命周期方法将被重新命名。
componentWillMount→UNSAFE_componentWillMountcomponentWillReceiveProps→UNSAFE_componentWillReceivePropscomponentWillUpdate→UNSAFE_componentWillUpdate
React 16.9并不包含破坏性的变化,旧的名称在这个版本中继续工作。但现在你在使用任何旧名称时都会看到一个警告。

正如警告所提示的,对于每个不安全的方法,通常有更好的方法。然而,也许你没有时间去迁移或测试这些组件。在这种情况下,我们建议运行一个"codemod "脚本,自动重命名它们。
cd your_project
npx react-codemod rename-unsafe-lifecycles
(注意,这里说的是npx ,而不是npm 。npx 是Node 6+默认附带的一个工具。)
运行这个codemod将用新的名字(如UNSAFE_componentWillMount )取代旧的名字,如componentWillMount 。

像UNSAFE_componentWillMount 这样的新名字将在React 16.9和React 17.x中继续工作。然而,新的UNSAFE_ 前缀将帮助有问题的组件在代码审查和调试环节中脱颖而出。(如果你愿意,你可以通过选择严格模式来进一步阻止它们在你的应用程序中的使用)。
注意
了解更多关于我们的版本政策和对稳定性的承诺。
废弃了javascript: URLs
以javascript: 开始的URL是一个危险的攻击面,因为很容易意外地在一个标签(如<a href> )中包含未经消毒的输出,从而产生一个安全漏洞。
const userProfile = {
website: "javascript: alert('you got hacked')",
};
// This will now warn:
<a href={userProfile.website}>Profile</a>
**在React 16.9中,**这种模式继续工作,但它会记录一个警告。如果你使用javascript: URLs的逻辑,试着使用React事件处理程序来代替。(作为最后的手段,你可以用以下方式规避保护 dangerouslySetInnerHTML来规避保护,但这是非常不可取的,而且往往会导致安全漏洞)。
**在未来的一个主要版本中,**如果遇到javascript: 的URL,React将抛出一个错误。
废弃的 "工厂 "组件
在用Babel编译JavaScript类变得流行之前,React支持一个 "工厂 "组件,它返回一个带有render 方法的对象。
function FactoryComponent() {
return { render() { return <div />; } }
}
这种模式令人困惑,因为它看起来太像一个函数组件--但它并不是。(在上面的例子中,函数组件只是返回<div /> )。
这种模式几乎从来没有在野外使用过,而且支持这种模式会导致React的体积和速度比必要的要大一些。所以我们在16.9中废除了这种模式,并在遇到这种情况时记录一个警告。如果你依赖它,添加FactoryComponent.prototype = React.Component.prototype 可以作为一种变通方法。另外,你也可以把它转换为一个类或一个函数组件。
我们预计大多数代码库不会受此影响。
新功能
异步 act()用于测试
React 16.8引入了一个新的测试工具,叫做 act()的测试工具,以帮助你编写更符合浏览器行为的测试。例如,单个act() 内的多个状态更新会被分批进行。这与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测试库来减少模板代码。它的许多方法已经在内部使用act() 。
如果你遇到任何其他情况,act() ,请在问题跟踪器上告诉我们,我们会努力帮助你。
性能测量 <React.Profiler>
在 React 16.5 中,我们为 DevTools引入了一个新的React Profiler,它可以帮助你找到应用程序中的性能瓶颈。在React 16.9中,我们还增加了一个程序化的方式来收集测量结果,称为<React.Profiler> 。我们希望大多数小型应用程序不会使用它,但它可以方便地跟踪大型应用程序的性能退步情况。
<Profiler> 衡量React应用的渲染频率以及渲染的 "成本 "是多少。它的目的是帮助识别应用程序中速度较慢的部分,并可能从优化中受益,如备忘录化。
一个<Profiler> ,可以添加到React树的任何地方,以衡量渲染树的那一部分的成本。它需要两个道具:一个id (字符串)和一个onRender 回调(函数),当树中的一个组件 "提交 "更新时,React会调用它。
render(
<Profiler id="application" onRender={onRenderCallback}> <App>
<Navigation {...props} />
<Main {...props} />
</App>
</Profiler>);
要了解更多关于Profiler 和传递给onRender 回调的参数,请查看 Profiler 文档。
注意。
剖析会增加一些额外的开销,所以**在生产构建**中禁用它。
要选择生产剖析,React提供了一个特殊的生产构建,并启用了剖析功能。 阅读更多关于如何使用这个构建的信息:fb.me/react-profi…。
显著的错误修正
这个版本还包含其他一些值得注意的改进。
- 修正了在
<Suspense>树内调用findDOMNode()时出现的崩溃。 - 保留被删除的子树所导致的内存泄漏也得到了修复。
- 在
useEffect中由setState引起的无限循环现在记录了一个错误。(这与你在类中的componentDidUpdate中调用setState时看到的错误类似)。
我们感谢所有帮助解决这些和其他问题的贡献者。你可以在下面找到完整的更新日志。
路线图的更新
在2018年11月,我们已经发布了这个16.x版本的路线图。
- 带有React Hooks的16.x小版本(过去估计:2019年第一季度)
- 一个带有并发模式的16.x小版本(过去估计:2019年第二季度)
- 一个带有数据获取暂停功能的16.x小版本(过去估计:2019年中)。
这些估计太乐观了,我们需要调整它们。
**tldr:**我们按时交付了Hooks,但我们将并发模式和数据获取的暂停重新组合为一个单一的版本,我们打算在今年晚些时候发布。
2月,我们发布了包括React Hooks在内的稳定的16.8版本,React Native支持将在一个月后推出。然而,我们低估了这个版本的后续工作,包括lint规则、开发者工具、例子和更多的文档。这使时间轴转移了几个月。
现在,React Hooks已经推出,关于数据获取的并发模式和暂停的工作正在紧锣密鼓地进行。目前正在积极开发的Facebook新网站就是建立在这些功能之上的。用真实的代码测试它们有助于在影响开源用户之前发现和解决许多问题。其中一些修复涉及到这些功能的内部重新设计,这也导致了时间轴的滑移。
有了这个新的认识,下面是我们下一步计划做的事情。
一个版本而不是两个版本
并发模式和悬念为正在积极开发的新Facebook网站提供动力,因此我们有信心,它们在技术上已经接近稳定状态。我们现在也更了解在它们准备好开源采用之前的具体步骤。
最初我们认为我们会把数据获取的并发模式和暂停功能分成两个版本。我们发现这样的顺序解释起来很混乱,因为这些功能的关联性比我们一开始想象的要大。所以我们计划在一个合并的版本中发布对并发模式和数据获取暂停的支持。
我们不想再过度承诺发布日期了。鉴于我们在生产代码中依赖这两者,我们期望在今年提供一个16.x版本,对它们进行选择支持。
关于数据获取的更新
虽然React对你如何获取数据没有意见,但用于数据获取的Suspense的第一个版本可能会专注于与有意见的数据获取库集成。例如,在Facebook,我们正在使用即将与Suspense集成的Relay API。我们将记录其他有意见的库,如Apollo,如何支持类似的整合。
在第一个版本中,我们不打算关注我们在早期演示中使用的 "发射HTTP请求 "的临时解决方案(也被称为 "React Cache")。然而,我们期望我们和React社区在首次发布后的几个月内都会探索这一领域。
关于服务器渲染的更新
我们已经开始了新的具有Suspense功能的服务器渲染器的工作,但我们不期望它能在并发模式的初始版本中准备好。然而,这个版本将提供一个临时的解决方案,让现有的服务器渲染器立即为Suspense回退发出HTML,然后在客户端渲染其真实内容。这是我们目前在Facebook自己使用的解决方案,直到流式渲染器准备就绪。
为什么要花这么长时间?
我们已经发布了通往并发模式的各个部分,因为它们变得稳定了,包括新的上下文API、使用Suspense的懒惰加载以及Hooks。我们也急于发布其他缺失的部分,但大规模地尝试它们是这个过程的重要部分。诚实的回答是,这只是花了比我们开始时预期更多的工作。像往常一样,我们感谢你在Twitter和我们的问题跟踪器中提出的问题和反馈。
安装
反应
React v16.9.0已经在npm注册表上提供。
要用Yarn安装React 16,请运行。
yarn add react@^16.9.0 react-dom@^16.9.0
要用npm安装React 16,请运行。
npm install --save react@^16.9.0 react-dom@^16.9.0
我们还通过CDN提供React的UMD构建。
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
详细的安装说明请参考文档。
更新日志
React
- 添加
<React.Profiler>API,以编程方式收集性能测量。(@bvaughnin#15172) - 移除
unstable_ConcurrentMode,改用unstable_createRoot。(@acdlitein#15532)
React DOM
- 弃用
UNSAFE_*生命周期方法的旧名称。(@bvaughnin#15186and@threepointonein#16103) - 废弃作为常见攻击面的
javascript:URLs。(@sebmarkbage在#15047) - 废弃不常见的 "模块模式"(工厂)组件。(@sebmarkbage在#15145)
- 在
<video>,增加对disablePictureInPicture属性的支持。(@eek在#15334) - 为
<embed>增加对onLoad事件的支持。(@cherniavskii在#15614) - 增加对从DevTools编辑
useState状态的支持。(@bvaughn在#14906) - 增加支持从DevTools切换Suspense的功能。(@gaearonin#15232)
- 当从
useEffect调用setState,创建一个循环时发出警告。(@gaearon在#15180) - 修复一个内存泄漏。(@paulshen在#16115)
- 修复了
findDOMNode里面的组件被包裹在<Suspense>的崩溃问题。(@acdlitein#15312) - 修复待定效果被刷新过晚的问题。(@acdlite在#15650)
- 修复警告信息中不正确的参数顺序。(@brickspert在#15345)
- 修复当有
!important风格时隐藏悬念回退节点。(@acdlitein#15861and#15882) - 略微提高水化性能。(@bmeurer在#15998)
React DOM服务器
React测试工具和测试渲染器
- 添加
act(async () => ...),用于测试异步状态的更新。(@threepointone在#14853) - 增加对不同渲染器嵌套
act的支持。(@threepointonein#16039and#16042) - 在严格模式下,如果特效被安排在
act()调用之外,则发出警告。(@threepointonein#15763and#16041) - 当从错误的渲染器中使用
act时发出警告。(@threepointonein#15756)