{"componentChunkName":"component---src-templates-blog-js","path":"/blog/2019/08/08/react-v16.9.0.html","result":{"data":{"markdownRemark":{"html":"<p>今天我们发布了 React 16.9。它包含几个新功能，bug 修复以及新的弃用警告，以助于筹备接下来的主要版本。</p>\n<h2 id=\"new-deprecations\"><a href=\"#new-deprecations\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>新的弃用 </h2>\n<h3 id=\"renaming-unsafe-lifecycle-methods\"><a href=\"#renaming-unsafe-lifecycle-methods\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>重命名 Unsafe 的生命周期方法 </h3>\n<p><a href=\"/blog/2018/03/27/update-on-async-rendering.html\">一年前</a>，我们宣布新的 unsafe 的生命周期方法正在进行重命名：</p>\n<ul>\n<li><code class=\"gatsby-code-text\">componentWillMount</code> → <code class=\"gatsby-code-text\">UNSAFE_componentWillMount</code></li>\n<li><code class=\"gatsby-code-text\">componentWillReceiveProps</code> → <code class=\"gatsby-code-text\">UNSAFE_componentWillReceiveProps</code></li>\n<li><code class=\"gatsby-code-text\">componentWillUpdate</code> → <code class=\"gatsby-code-text\">UNSAFE_componentWillUpdate</code></li>\n</ul>\n<p><strong>React 16.9 未包含破坏性更改，并且旧的生命周期方法名在此版本继续沿用。</strong> 但当你使用旧的生命周期方法名时，你将看到如下警告：</p>\n<p><img src=\"https://i.imgur.com/sngxSML.png\" alt=\"Warning: componentWillMount has been renamed, and is not recommended for use.\"></p>\n<p>正如警告所示，对于每种 unsafe 的方法来说，通常都有<a href=\"/blog/2018/03/27/update-on-async-rendering.html#migrating-from-legacy-lifecycles\">更好的解决方案</a>。但你可能没有时间迁移或测试这些组件。在这种情况下，我们建议你运行一个自动重命名的 <a href=\"https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">“codemod”</a> 脚本：</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"gatsby-code-bash\"><code class=\"gatsby-code-bash\"><span class=\"token builtin class-name\">cd</span> your_project\nnpx react-codemod rename-unsafe-lifecycles</code></pre></div>\n<p><em>（请注意，这里使用了 <code class=\"gatsby-code-text\">npx</code>，而非 <code class=\"gatsby-code-text\">npm</code>。<code class=\"gatsby-code-text\">npx</code> 是 Node 6+ 默认提供的实用工具）</em></p>\n<p>运行 codemod 会将旧的生命周期方法名替换，例如 <code class=\"gatsby-code-text\">componentWillMount</code> 会被替换为 <code class=\"gatsby-code-text\">UNSAFE_componentWillMount</code>：</p>\n<p><img src=\"https://i.imgur.com/Heyvcyi.gif\" alt=\"Codemod in action\"></p>\n<p>新的方法名（如 <code class=\"gatsby-code-text\">UNSAFE_componentWillMount</code>）<strong>在 React 16.9 和 React 17.x 中，仍可以继续使用</strong>。但是，新的 <code class=\"gatsby-code-text\">UNSAFE_</code> 前缀将有助于在代码 review 和 debug 期间，使这些有问题的字样更突出。（你也可以按照自己的意愿，在你的应用中选择性的引入 <a href=\"/docs/strict-mode.html\">严格模式（Strict Mode）</a> 来进一步阻止大家使用它们）。</p>\n<blockquote>\n<p>注意</p>\n<p>了解更多关于 <a href=\"/docs/faq-versioning.html#commitment-to-stability\">版本策略及对稳定性的承诺</a>。</p>\n</blockquote>\n<h3 id=\"deprecating-javascript-urls\"><a href=\"#deprecating-javascript-urls\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>废弃 <code class=\"gatsby-code-text\">javascript:</code> 形式的 URL </h3>\n<p>以 <code class=\"gatsby-code-text\">javascript:</code> 开头的 URL 非常容易遭受攻击，因为它很容易在诸如 <code class=\"gatsby-code-text\">&lt;a href&gt;</code> 之类的标签中引入未经过处理的输出并会造成安全漏洞：</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> userProfile <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  website<span class=\"token operator\">:</span> <span class=\"token string\">\"javascript: alert('you got hacked')\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 此处现在会有警告</span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>a</span> <span class=\"token attr-name\">href</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>userProfile<span class=\"token punctuation\">.</span>website<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Profile</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>a</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p><strong>在 React 16.9 中，</strong> 这种模式将继续有效，但它将输出一个警告。如果你需使用 <code class=\"gatsby-code-text\">javascript:</code> 形式的 URL 作为逻辑，请尝试使用 React 的事件处理程序替代。（万不得已时，你可以使用 <a href=\"/docs/dom-elements.html#dangerouslysetinnerhtml\"><code class=\"gatsby-code-text\">dangerouslySetInnerHTML</code></a> 来规避保护，但是这样并不被推荐且经常导致安全漏洞。）</p>\n<p><strong>未来的主要版本中，</strong> 如果遇到 <code class=\"gatsby-code-text\">javascript:</code> 形式的 URL，React 将抛出错误。</p>\n<h3 id=\"deprecating-factory-components\"><a href=\"#deprecating-factory-components\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>废弃 “Factory” 组件 </h3>\n<p>在使用 Babel 编译 JavaScript Class 成为主流前，React 支持 “factory” 组件，该组件使用 <code class=\"gatsby-code-text\">render</code> 方法返回一个对象：</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">FactoryComponent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span> <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>这种方式令人困惑，因为它看起来像函数组件 —— 但它并不是。（函数组件只返回示例中的 <code class=\"gatsby-code-text\">&lt;div /&gt;</code>。）</p>\n<p>这种方式几乎从未被广泛使用过，并且支持它会导致 React 变大且变慢。因此，我们在 16.9 中逐步弃用此模式，并在遇到时输出警告。如果项目中依赖了此组件，可以通过添加 <code class=\"gatsby-code-text\">FactoryComponent.prototype = React.Component.prototype</code> 作为解决方案。或者你可以直接将其转换为 class 组件或函数组件。</p>\n<p>我们不希望大多数代码库受到此影响。</p>\n<h2 id=\"new-features\"><a href=\"#new-features\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>新特性 </h2>\n<h3 id=\"async-act-for-testing\"><a href=\"#async-act-for-testing\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>用于测试的异步函数 <a href=\"/docs/test-utils.html#act\"><code class=\"gatsby-code-text\">act()</code></a> </h3>\n<p><a href=\"/blog/2019/02/06/react-v16.8.0.html\">React 16.8</a> 引入了名为 <a href=\"/docs/test-utils.html#act\"><code class=\"gatsby-code-text\">act()</code></a> 的新测试实用工具来帮助你编写更符合浏览器行为的测试代码。例如，单个 <code class=\"gatsby-code-text\">act()</code> 中的多个状态更新会进行批处理。这与 React 在处理真实浏览器事件时的工作方式相匹配，并有助于为将来 React 更频繁地批量更新组件做准备。</p>\n<p>然而，在 16.8 中的 <code class=\"gatsby-code-text\">act()</code> 仅支持同步函数。有时，你可能会在测试时看到类似的警告，但<a href=\"https://github.com/facebook/react/issues/14769\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">无法轻易修复</a>：</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"gatsby-code-text\"><code class=\"gatsby-code-text\">An update to SomeComponent inside a test was not wrapped in act(...).</code></pre></div>\n<p><strong>在 React 16.9 中，<code class=\"gatsby-code-text\">act()</code> 也支持异步函数，</strong> 并且你可以在调用它时使用 <code class=\"gatsby-code-text\">await</code>：</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">await</span> <span class=\"token function\">act</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>这就解决了之前无法使用 <code class=\"gatsby-code-text\">act()</code> 的情况，如当 state 更新发生在异步函数内时。因此 <strong>现在你应该能在测试中修复所有有关 <code class=\"gatsby-code-text\">act()</code> 的警告了。</strong></p>\n<p>我们了解到没有足够的信息来说明如何使用 <code class=\"gatsby-code-text\">act()</code> 来编写测试。新的<a href=\"/docs/testing-recipes.html\">测试技巧</a>一文描述了场景的场景，以及 <code class=\"gatsby-code-text\">act()</code> 如何帮助你编写优秀的测试。这些示例采用了原生 DOM API，但你可以使用 <a href=\"https://testing-library.com/docs/react-testing-library/intro\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Testing Library</a> 来减少样板代码（boilerplate code）。它的许多方法已经在实现上运用了 <code class=\"gatsby-code-text\">act()</code>。</p>\n<p>如果你遇到 <code class=\"gatsby-code-text\">act()</code> 的相关问题，请提出 <a href=\"https://github.com/facebook/react/issues\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">issue</a> 告知我们，我们会尽力提供帮助。</p>\n<h3 id=\"performance-measurements-with-reactprofiler\"><a href=\"#performance-measurements-with-reactprofiler\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>使用 <a href=\"/docs/profiler.html\"><code class=\"gatsby-code-text\">&lt;React.Profiler&gt;</code></a> 进行性能评估 </h3>\n<p>在 React 16.5 中，我们推出了新的 <a href=\"/blog/2018/09/10/introducing-the-react-profiler.html\">React Profiler for DevTools</a>，它可以帮你找出应用程序中的性能瓶颈。<strong>在 React 16.9 中，我们还提供了一种通过<em>编程</em>的方式来收集测量你的代码</strong>，这种方式被称为 <code class=\"gatsby-code-text\">&lt;React.Profiler&gt;</code>。我们预计大多数较小的应用都不会使用它，但在较大的应用中追踪性能回归可能会很方便。</p>\n<p><code class=\"gatsby-code-text\">&lt;Profiler&gt;</code> 能测量 React 应用程序渲染的频率以及渲染的 “成本”。其目的是帮助标识应用程序中渲染缓慢的部分，并可能会更易于进行 <a href=\"/docs/hooks-faq.html#how-to-memoize-calculations\">memoization</a> 等优化。</p>\n<p><code class=\"gatsby-code-text\">&lt;Profiler&gt;</code> 可以在 React 树中的任意位置添加，以评估渲染树中对应位置的成本。\n它依赖两个 props：<code class=\"gatsby-code-text\">id</code> (string) 和 <a href=\"/docs/profiler.html#onrender-callback\"><code class=\"gatsby-code-text\">onRender</code> 回调</a> (function)，当树中的组件 “提交（commit）” 更新时， React 就会调用它。</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token function\">render</span><span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Profiler</span></span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>application<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">onRender</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>onRenderCallback<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">App</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Navigation</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Main</span></span> <span class=\"token spread\"><span class=\"token punctuation\">{</span><span class=\"token punctuation\">...</span><span class=\"token attr-value\">props</span><span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">App</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token plain-text\">  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">Profiler</span></span><span class=\"token punctuation\">></span></span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p> 欲了解有关 <code class=\"gatsby-code-text\">Profiler</code> 和传递给 <code class=\"gatsby-code-text\">onRender</code> 回调参数的更多信息，请参阅 <a href=\"/docs/profiler.html\"><code class=\"gatsby-code-text\">Profiler</code> 文档</a>。</p>\n<blockquote>\n<p>注意:</p>\n<p>性能分析会增加额外的开销，因此它<strong>在<a href=\"https://reactjs.org/docs/optimizing-performance.html#use-the-production-build\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">生产构建</a>中会被禁用</strong>。</p>\n<p>如果想要在生产环境进行性能分析，React 提供了一个特殊的生成构建，并启用了分析模式。\n在 <a href=\"https://fb.me/react-profiling\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">fb.me/react-profiling</a> 中阅读有关如何使用此构建的更多信息。</p>\n</blockquote>\n<h2 id=\"notable-bugfixes\"><a href=\"#notable-bugfixes\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>值得注意的 bug 修复 </h2>\n<p>此版本包含一些其他显著的改进：</p>\n<ul>\n<li>在 <code class=\"gatsby-code-text\">&lt;Suspense&gt;</code> 树中调用 <code class=\"gatsby-code-text\">findDOMNode()</code> 时出现崩溃的情况。<a href=\"https://github.com/facebook/react/pull/15312\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">已修复</a>。</li>\n<li>保留已删除的子树导致的内存泄露。<a href=\"https://github.com/facebook/react/pull/16115\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">已修复</a>。</li>\n<li>由 <code class=\"gatsby-code-text\">useEffect</code> 中 <code class=\"gatsby-code-text\">setState</code> 引起的无限循环，现在会<a href=\"https://github.com/facebook/react/pull/15180\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">输出错误</a>。（这与在 class 组件中的 <code class=\"gatsby-code-text\">componentDidUpdate</code> 调用 <code class=\"gatsby-code-text\">setState</code> 时看到的错误一致。）</li>\n</ul>\n<p>感谢所有帮助解决这些问题的贡献者。你可以在<a href=\"#changelog\">此处</a>找到完整的更新日志。</p>\n<h2 id=\"an-update-to-the-roadmap\"><a href=\"#an-update-to-the-roadmap\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Roadmap 的进展 </h2>\n<p><a href=\"/blog/2018/11/27/react-16-roadmap.html\">2018 年 11 月</a>我们发布了 16.x 版本的 roadmap：</p>\n<ul>\n<li>实现 React Hooks 的 16.x 小版本（预估：Q1 2019）</li>\n<li>实现 Concurrent Mode 的 16.x 小版本 (预估：Q2 2019)</li>\n<li>实现 Suspense for Data Fetching (预估：2019 年中)</li>\n</ul>\n<p>这些预估过于理想化，我们需要进行调整。</p>\n<p><strong>tldr：</strong> 我们按时发布了 Hook，但我们正在将 Concurrent Mode 和 Suspense for Data Fetching 重组为今年晚些时候的单个版本。</p>\n<p>2 月份时，我们在<a href=\"/blog/2019/02/06/react-v16.8.0.html\">发布的稳定 16.8 版本</a>中引入了 React Hook，React Native 在<a href=\"https://reactnative.dev/blog/2019/03/12/releasing-react-native-059\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">一个月后</a>也进行了支持。但是，我们低估了此版本的后续工作，其中包括 lint 规则，developer tools，示例以及更多文档。这使得时间线发生了改变。</p>\n<p>现在 React Hook 已经推出，Concurrent Mode 和 Suspense for Data Fetching 的工作正在全面展开。<a href=\"https://twitter.com/facebook/status/1123322299418124289\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">目前正在进行 Facebook 新网站的研发工作</a> 是建立在这些特性基础之上的。使用真实代码环境对它们进行测试有助于在影响开源用户之前发现并解决许多未知问题。其中一些修复涉及到这些特性的内部重新设计，这也导致时间的推迟。</p>\n<p>望大家理解，这就是我们接下来的计划。</p>\n<h3 id=\"one-release-instead-of-two\"><a href=\"#one-release-instead-of-two\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>一个版本而不是两个版本 </h3>\n<p>Concurrent Mode 和 Suspense <a href=\"https://developers.facebook.com/videos/2019/building-the-new-facebookcom-with-react-graphql-and-relay/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">驱动了 Facebook 新网站的研发</a>，这个项目目前在积极的开发中，因此我们可以很自信的说，从技术上讲，Concurrent Mode 和 Suspense 已近乎稳定了。同时，我们也更加清楚，在它们被开源使用之前我们应该具体做哪些步骤。</p>\n<p>最开始，我们觉得为了实现 Data Fetching（数据请求），我们需要把 Concurrent Mode 和 Suspense 拆分为两个版本。后来我们发现，这个顺序很难说的通，因为这些特性之间的关系比我们当初想象的更为密切。因此，我们计划为 Data Fetching 发布一个同时支持 Concurrent Mode 和 Suspense 的单个版本。</p>\n<p>我们不想再次过度承诺发布日期。考虑到我们在生产环境的代码中同时依赖了这两者，我们期望今年的 16.x 的某个版本中，支持可以选择性的使用它们。</p>\n<h3 id=\"an-update-on-data-fetching\"><a href=\"#an-update-on-data-fetching\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Data Fetching 的进展 </h3>\n<p>虽然 React 没有规定你如何请求数据，但是第一版用来请求数据的 Suspense 很有可能专注于集成<em>固定的数据请求库</em>。比如，在 Facebook，我们正在使用即将发布的集成了 Suspense 的 Relay APIs。我们也将会给出对其他库（比如 Apollo）做类似的整合的文档。</p>\n<p>在第一个版本中，我们<em>并没有</em>打算专注于我们在早期演示中（也称为“React Cache”）使用的临时 “触发HTTP请求” 解决方案。但是，我们希望我们和 React 社区将在首次发布后的几个月内仍会在这个领域继续探索。</p>\n<h3 id=\"an-update-on-server-rendering\"><a href=\"#an-update-on-server-rendering\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>服务端渲染的进展 </h3>\n<p>我们已经开始研究<a href=\"/blog/2018/11/27/react-16-roadmap.html#suspense-for-server-rendering\">新的支持 Suspense 的服务器端渲染引擎</a>，但是我们<em>不认为</em>它在并发模式的最初版本将会就绪。然而，这个版本将会提供一个临时的解决方案，这个方案可以让现有的服务端渲染引擎在 Suspense 的回调函数中立即生成 HTML，然后在客户端渲染出真正的内容。这就是我们在流式渲染引擎就绪之前，当前在 Facebook 内部使用的方案。</p>\n<h3 id=\"why-is-it-taking-so-long\"><a href=\"#why-is-it-taking-so-long\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>为什么要花费这么久时间？</h3>\n<p>随着每个单独的部件趋于稳定，我们将它们迁移到了并发模式中，其中包括了 <a href=\"/blog/2018/03/29/react-v-16-3.html\">新的 context API</a>、<a href=\"/blog/2018/10/23/react-v-16-6.html\">含有 Suspense 的懒加载</a> 以及 <a href=\"/blog/2019/02/06/react-v16.8.0.html\">Hook</a>。我们也十分期望发布其他缺失的部分，但是<a href=\"/docs/design-principles.html#dogfooding\">大规模尝试它们</a>是这个过程中一个很重要的部分。坦诚地说，我们比最开始预想投入了更多的工作。我们会一如既往，感谢你在 <a href=\"https://twitter.com/reactjs\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Twitter</a> 和 <a href=\"https://github.com/facebook/react/issues\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">问题跟踪</a> 中提出的问题和反馈。</p>\n<h2 id=\"installation\"><a href=\"#installation\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>安装 </h2>\n<h3 id=\"react\"><a href=\"#react\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>React </h3>\n<p>npm registry 中提供了 React v16.9.0。</p>\n<p>使用 yarn 安装 React 16，执行如下命令：</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"gatsby-code-bash\"><code class=\"gatsby-code-bash\"><span class=\"token function\">yarn</span> <span class=\"token function\">add</span> react@^16.9.0 react-dom@^16.9.0</code></pre></div>\n<p>使用 npm 安装 React 16，执行如下命令：</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"gatsby-code-bash\"><code class=\"gatsby-code-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save react@^16.9.0 react-dom@^16.9.0</code></pre></div>\n<p>我们还通过 CDN 提供了 React 的 UMD 版本：</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"gatsby-code-html\"><code class=\"gatsby-code-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">crossorigin</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>https://unpkg.com/react@16/umd/react.production.min.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">crossorigin</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>https://unpkg.com/react-dom@16/umd/react-dom.production.min.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>请参阅<a href=\"/docs/installation.html\">详细安装说明文档</a>。</p>\n<h2 id=\"changelog\"><a href=\"#changelog\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Changelog </h2>\n<h3 id=\"react\"><a href=\"#react\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>React </h3>\n<ul>\n<li>提供 <code class=\"gatsby-code-text\">&lt;React.Profiler&gt;</code> API 实现以编程的方式进行性能评估。(<a href=\"https://github.com/bvaughn\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/15172\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15172</a>)</li>\n<li>删除 <code class=\"gatsby-code-text\">unstable_ConcurrentMode</code> 以支持 <code class=\"gatsby-code-text\">unstable_createRoot</code>。(<a href=\"https://github.com/acdlite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15532\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15532</a>)</li>\n</ul>\n<h3 id=\"react-dom\"><a href=\"#react-dom\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>React DOM </h3>\n<ul>\n<li>弃用以 <code class=\"gatsby-code-text\">UNSAFE_*</code> 开头的旧生命周期方法。(<a href=\"https://github.com/bvaughn\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/15186\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15186</a> and <a href=\"https://github.com/threepointone\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/16103\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16103</a>)</li>\n<li>弃用 <code class=\"gatsby-code-text\">javascript:</code> 形式的 URL。 (<a href=\"https://github.com/sebmarkbage\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/15047\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15047</a>)</li>\n<li>弃用不常用的 “module pattern” (factory) 组件。 (<a href=\"https://github.com/sebmarkbage\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/15145\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15145</a>)</li>\n<li>在 <code class=\"gatsby-code-text\">&lt;video&gt;</code> 组件上添加对 <code class=\"gatsby-code-text\">disablePictureInPicture</code> 属性的支持。(<a href=\"https://github.com/eek\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@eek</a> in <a href=\"https://github.com/facebook/react/pull/15334\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15334</a>)</li>\n<li>为 <code class=\"gatsby-code-text\">&lt;embed&gt;</code> 添加对 <code class=\"gatsby-code-text\">onLoad</code> 事件的支持。(<a href=\"https://github.com/cherniavskii\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@cherniavskii</a> in <a href=\"https://github.com/facebook/react/pull/15614\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15614</a>)</li>\n<li>为在 DevTools 中编辑 <code class=\"gatsby-code-text\">useState</code> 的 state 提供支持。(<a href=\"https://github.com/bvaughn\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/14906\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#14906</a>)</li>\n<li>为在 DevTools 中切换 Suspense 提供支持。(<a href=\"https://github.com/gaearon\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/15232\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15232</a>)</li>\n<li>当 <code class=\"gatsby-code-text\">setState</code> 在 <code class=\"gatsby-code-text\">useEffect</code> 中循环调用时，发出警告。(<a href=\"https://github.com/gaearon\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/15180\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15180</a>)</li>\n<li>修复内存泄露。(<a href=\"https://github.com/paulshen\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@paulshen</a> in <a href=\"https://github.com/facebook/react/pull/16115\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16115</a>)</li>\n<li>修复 <code class=\"gatsby-code-text\">&lt;Suspense&gt;</code> 包裹的组件中使用 <code class=\"gatsby-code-text\">findDOMNode</code> 发生崩溃的问题。(<a href=\"https://github.com/acdlite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15312\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15312</a>)</li>\n<li>修复因为刷新太晚而导致 pending effect 的情况。(<a href=\"https://github.com/acdlite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15650\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15650</a>)</li>\n<li>修复警告信息中不正确的参数顺序。(<a href=\"https://github.com/brickspert\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@brickspert</a> in <a href=\"https://github.com/facebook/react/pull/15345\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15345</a>)</li>\n<li>修复当存在 <code class=\"gatsby-code-text\">!important</code> 样式时，隐藏 Suspense 降级节点的问题。(<a href=\"https://github.com/acdlite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15861\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15861</a> and <a href=\"https://github.com/facebook/react/pull/15882\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15882</a>)</li>\n<li>提高 hydration 的性能。(<a href=\"https://github.com/bmeurer\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@bmeurer</a> in <a href=\"https://github.com/facebook/react/pull/15998\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15998</a>)</li>\n</ul>\n<h3 id=\"react-dom-server\"><a href=\"#react-dom-server\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>React DOM Server </h3>\n<ul>\n<li>修复 camelCase 自定义 CSS 属性名称的错误输出。(<a href=\"https://github.com/bedakb\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@bedakb</a> in <a href=\"https://github.com/facebook/react/pull/16167\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16167</a>)</li>\n</ul>\n<h3 id=\"react-test-utilities-and-test-renderer\"><a href=\"#react-test-utilities-and-test-renderer\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>React Test Utilities and Test Renderer </h3>\n<ul>\n<li>添加 <code class=\"gatsby-code-text\">act(async () =&gt; ...)</code> 来测试异步状态更新。(<a href=\"https://github.com/threepointone\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/14853\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#14853</a>)</li>\n<li>添加对不同渲染器嵌套 <code class=\"gatsby-code-text\">act</code> 的支持。 (<a href=\"https://github.com/threepointone\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/16039\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16039</a> and <a href=\"https://github.com/facebook/react/pull/16042\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16042</a>)</li>\n<li>在严格模式下，如果副作用函数在 <code class=\"gatsby-code-text\">act</code> 之外被调用，就会发出警告。(<a href=\"https://github.com/threepointone\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/15763\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15763</a> and <a href=\"https://github.com/facebook/react/pull/16041\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#16041</a>)</li>\n<li>当在错误的渲染器中使用 <code class=\"gatsby-code-text\">act</code> 时发出警告。(<a href=\"https://github.com/threepointone\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/15756\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">#15756</a>)</li>\n</ul>","excerpt":"今天我们发布了 React 16.9。它包含几个新功能，bug 修复以及新的弃用警告，以助于筹备接下来的主要版本。 新的弃用  重命名 Unsafe 的生命周期方法  一年前，我们宣布新的 unsafe 的生命周期方法正在进行重命名：  →   →   →  React 16.9 未包含破坏性更改，并且旧的生命周期方法名在此版本继续沿用。 但当你使用旧的生命周期方法名时，你将看到如下警告： Warning: componentWillMount has been renamed, and is not recommended for use. 正如警告所示，对于每种 unsafe 的方法来说，通常都有更好的解决方案。但你可能没有时间迁移或测试这些组件。在这种情况下，我们建议你运行一个自动重命名的 “codemod” 脚本： （请注意，这里使用了 ，而非 。 是 Node 6+ 默认提供的实用工具） 运行 codemod 会将旧的生命周期方法名替换，例如  会被替换为 ： Codemod in action 新的方法名（如 ）在 React 16.9 和 React 17.x…","frontmatter":{"title":"React v16.9.0 发布及 Roadmap 最新进展","next":null,"prev":null,"author":[{"frontmatter":{"name":"Dan Abramov","url":"https://twitter.com/dan_abramov"}},{"frontmatter":{"name":"Brian Vaughn","url":"https://github.com/bvaughn"}}]},"fields":{"date":"August 08, 2019","path":"content/blog/2019-08-08-react-v16.9.0.md","slug":"/blog/2019/08/08/react-v16.9.0.html"}},"allMarkdownRemark":{"edges":[{"node":{"frontmatter":{"title":"React v16.13.0"},"fields":{"slug":"/blog/2020/02/26/react-v16.13.0.html"}}},{"node":{"frontmatter":{"title":"Building Great User Experiences with Concurrent Mode and Suspense"},"fields":{"slug":"/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html"}}},{"node":{"frontmatter":{"title":"使用 React 预发布版为新功能打基础"},"fields":{"slug":"/blog/2019/10/22/react-release-channels.html"}}},{"node":{"frontmatter":{"title":"全新的 React DevTools 简介"},"fields":{"slug":"/blog/2019/08/15/new-react-devtools.html"}}},{"node":{"frontmatter":{"title":"React v16.9.0 发布及 Roadmap 最新进展"},"fields":{"slug":"/blog/2019/08/08/react-v16.9.0.html"}}},{"node":{"frontmatter":{"title":"Is React Translated Yet? ¡Sí! Sim! はい！"},"fields":{"slug":"/blog/2019/02/23/is-react-translated-yet.html"}}},{"node":{"frontmatter":{"title":"React v16.8：Hook 发布"},"fields":{"slug":"/blog/2019/02/06/react-v16.8.0.html"}}},{"node":{"frontmatter":{"title":"React v16.7：不包含 Hook 的版本"},"fields":{"slug":"/blog/2018/12/19/react-v-16-7.html"}}},{"node":{"frontmatter":{"title":"React 16.x 的规划"},"fields":{"slug":"/blog/2018/11/27/react-16-roadmap.html"}}},{"node":{"frontmatter":{"title":"React Conf 会议纪要：Hook，Suspense 和 Concurrent Rendering"},"fields":{"slug":"/blog/2018/11/13/react-conf-recap.html"}}}]}},"pageContext":{"slug":"/blog/2019/08/08/react-v16.9.0.html"}}}