---
source: src/feeds/rss.rs
expression: result
---
[
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2018/10/23/react-v-16-6.html",
        link: "https://reactjs.org/blog/2018/10/23/react-v-16-6.html",
        title: "React v16.6.0: lazy, memo and contextType",
        date: 2018-10-23T00:00:00Z,
        summary: Some(
            "Today we‚Äôre releasing React 16.6 with a few new convenient features. A form of PureComponent/shouldComponentUpdate for function components, a way to do code splitting using Suspense and an easier way to consume Context from class components.\nCheck out the full changelog below.\nReact.memo \nClass components can bail out from rendering when their input props are the same using PureComponent or shouldComponentUpdate. Now you can do the same with function components by wrapping them in React.memo.\nconst MyComponent = React.memo(function MyComponent(props) {\n  /* only rerenders if props change */\n});\nReact.lazy: Code-Splitting with Suspense \nYou may have seen Dan‚Äôs talk about React Suspense at JSConf Iceland. Now you can use the Suspense component to do code-splitting by wrapping a dynamic import in a call to React.lazy().\nimport React, {lazy, Suspense} from \'react\';\nconst OtherComponent = lazy(() =&gt; import(\'./OtherComponent\'));\n\nfunction MyComponent() {\n  return (\n    &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;\n      &lt;OtherComponent /&gt;\n    &lt;/Suspense&gt;\n  );\n}\nThe Suspense component will also allow library authors to start building data fetching with Suspense support in the future.\n\nNote: This feature is not yet available for server-side rendering. Suspense support will be added in a later release.\n\nstatic contextType \nIn React 16.3 we introduced the official Context API as a replacement to the previous Legacy Context API.\nconst MyContext = React.createContext();\nWe‚Äôve heard feedback that adopting the new render prop API can be difficult in class components. So we‚Äôve added a convenience API to consume a context value from within a class component.\nclass MyClass extends React.Component {\n  static contextType = MyContext;\n  componentDidMount() {\n    let value = this.context;\n    /* perform a side-effect at mount using the value of MyContext */\n  }\n  componentDidUpdate() {\n    let value = this.context;\n    /* ... */\n  }\n  componentWillUnmount() {\n    let value = this.context;\n    /* ... */\n  }\n  render() {\n    let value = this.context;\n    /* render something based on the value of MyContext */\n  }\n}\nstatic getDerivedStateFromError() \nReact 16 introduced Error Boundaries for handling errors thrown in React renders. We already had the componentDidCatch lifecycle method which gets fired after an error has already happened. It‚Äôs great for logging errors to the server. It also lets you show a different UI to the user by calling setState.\nBefore that is fired, we render null in place of the tree that threw an error. This sometimes breaks parent components that don‚Äôt expect their refs to be empty. It also doesn‚Äôt work to recover from errors on the server since the Did lifecycle methods don‚Äôt fire during server-side rendering.\nWe‚Äôre adding another error method that lets you render the fallback UI before the render completes. See the docs for getDerivedStateFromError().\n\nNote: getDerivedStateFromError() is not yet available for server-side rendering. It is designed to work with server-side rendering in a future release. We‚Äôre releasing it early so that you can start preparing to use it.\n\nDeprecations in StrictMode \nIn 16.3 we introduced the StrictMode component. It lets you opt-in to early warnings for patterns that might cause problems in the future.\nWe‚Äôve added two more APIs to the list of deprecated APIs in StrictMode. If you don‚Äôt use StrictMode you don‚Äôt have to worry; these warning won‚Äôt fire for you.\n\nReactDOM.findDOMNode() - This API is often misunderstood and most uses of it are unnecessary. It can also be surprisingly slow in React 16. See the docs for possible upgrade paths.\nLegacy Context using contextTypes and getChildContext - Legacy context makes React slightly slower and bigger than it needs to be. That‚Äôs why we strongly want to encourage upgrading to the new context API. Hopefully the addition of the contextType API makes this a bit easier.\n\nIf you‚Äôre having trouble upgrading, we‚Äôd like to hear your feedback.\nInstallation \nReact v16.6.0 is available on the npm registry.\nTo install React 16 with Yarn, run:\nyarn add react@^16.6.0 react-dom@^16.6.0\nTo install React 16 with npm, run:\nnpm install --save react@^16.6.0 react-dom@^16.6.0\nWe also provide UMD builds of React via a CDN:\n&lt;script crossorigin src=\"https://unpkg.com/react@16/umd/react.production.min.js\"&gt;&lt;/script&gt;\n&lt;script crossorigin src=\"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js\"&gt;&lt;/script&gt;\nRefer to the documentation for detailed installation instructions.\nChangelog \nReact \n\nAdd React.memo() as an alternative to PureComponent for functions. (@acdlite in #13748)\nAdd React.lazy() for code splitting components. (@acdlite in #13885)\nReact.StrictMode now warns about legacy context API. (@bvaughn in #13760)\nReact.StrictMode now warns about findDOMNode. (@sebmarkbage in #13841)\nRename unstable_AsyncMode to unstable_ConcurrentMode. (@trueadm in #13732)\nRename unstable_Placeholder to Suspense, and delayMs to maxDuration. (@gaearon in #13799 and @sebmarkbage in #13922)\n\nReact DOM \n\nAdd contextType as a more ergonomic way to subscribe to context from a class. (@bvaughn in #13728)\nAdd getDerivedStateFromError lifecycle method for catching errors in a future asynchronous server-side renderer. (@bvaughn in #13746)\nWarn when &lt;Context&gt; is used instead of &lt;Context.Consumer&gt;. (@trueadm in #13829)\nFix gray overlay on iOS Safari. (@philipp-spiess in #13778)\nFix a bug caused by overwriting window.event in development. (@sergei-startsev in #13697)\n\nReact DOM Server \n\nAdd support for React.memo(). (@alexmckenley in #13855)\nAdd support for contextType. (@alexmckenley and @sebmarkbage in #13889)\n\nScheduler (Experimental) \n\nRename the package to scheduler. (@gaearon in #13683)\nSupport priority levels, continuations, and wrapped callbacks. (@acdlite in #13720 and #13842)\nImprove the fallback mechanism in non-DOM environments. (@acdlite in #13740)\nSchedule requestAnimationFrame earlier. (@acdlite in #13785)\nFix the DOM detection to be more thorough. (@trueadm in #13731)\nFix bugs with interaction tracing. (@bvaughn in #13590)\nAdd the envify transform to the package. (@mridgway in #13766)\n",
        ),
        content: Some(
            "<p>Today we‚Äôre releasing React 16.6 with a few new convenient features. A form of PureComponent/shouldComponentUpdate for function components, a way to do code splitting using Suspense and an easier way to consume Context from class components.</p>\n<p>Check out the full <a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#changelog\" rel=\"noopener noreferrer\">changelog</a> below.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#reactmemo\" rel=\"noopener noreferrer\"></a><a href=\"https://reactjs.org/docs/react-api.html#reactmemo\" rel=\"noopener noreferrer\"><code>React.memo</code></a> </h2>\n<p>Class components can bail out from rendering when their input props are the same using <a href=\"https://reactjs.org/docs/react-api.html#reactpurecomponent\" rel=\"noopener noreferrer\"><code>PureComponent</code></a> or <a href=\"https://reactjs.org/docs/react-component.html#shouldcomponentupdate\" rel=\"noopener noreferrer\"><code>shouldComponentUpdate</code></a>. Now you can do the same with function components by wrapping them in <a href=\"https://reactjs.org/docs/react-api.html#reactmemo\" rel=\"noopener noreferrer\"><code>React.memo</code></a>.</p>\n<div><pre><code><span>const</span> MyComponent <span>=</span> React<span>.</span><span>memo</span><span>(</span><span>function</span> <span>MyComponent</span><span>(</span>props<span>)</span> <span>{</span>\n  <span>/* only rerenders if props change */</span>\n<span>}</span><span>)</span><span>;</span></code></pre></div>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#reactlazy-code-splitting-with-suspense\" rel=\"noopener noreferrer\"></a><a href=\"https://reactjs.org/docs/code-splitting.html#reactlazy\" rel=\"noopener noreferrer\"><code>React.lazy</code></a>: Code-Splitting with <code>Suspense</code> </h2>\n<p>You may have seen <a href=\"https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html\" rel=\"noopener noreferrer\">Dan‚Äôs talk about React Suspense at JSConf Iceland</a>. Now you can use the Suspense component to do <a href=\"https://reactjs.org/docs/code-splitting.html#reactlazy\" rel=\"noopener noreferrer\">code-splitting</a> by wrapping a dynamic import in a call to <code>React.lazy()</code>.</p>\n<div><pre><code><span>import</span> React<span>,</span> <span>{</span>lazy<span>,</span> Suspense<span>}</span> <span>from</span> <span>\'react\'</span><span>;</span>\n<span>const</span> OtherComponent <span>=</span> <span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>import</span><span>(</span><span>\'./OtherComponent\'</span><span>)</span><span>)</span><span>;</span>\n\n<span>function</span> <span>MyComponent</span><span>(</span><span>)</span> <span>{</span>\n  <span>return</span> <span>(</span>\n    <span><span><span>&lt;</span>Suspense</span> <span>fallback</span><span><span>=</span><span>{</span><span><span><span>&lt;</span>div</span><span>&gt;</span></span><span>Loading...</span><span><span><span>&lt;/</span>div</span><span>&gt;</span></span><span>}</span></span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>OtherComponent</span> <span>/&gt;</span></span><span>\n    </span><span><span><span>&lt;/</span>Suspense</span><span>&gt;</span></span>\n  <span>)</span><span>;</span>\n<span>}</span></code></pre></div>\n<p>The Suspense component will also allow library authors to start building data fetching with Suspense support in the future.</p>\n<blockquote>\n<p>Note: This feature is not yet available for server-side rendering. Suspense support will be added in a later release.</p>\n</blockquote>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#static-contexttype\" rel=\"noopener noreferrer\"></a><a href=\"https://reactjs.org/docs/context.html#classcontexttype\" rel=\"noopener noreferrer\"><code>static contextType</code></a> </h2>\n<p>In <a href=\"https://reactjs.org/blog/2018/03/29/react-v-16-3.html\" rel=\"noopener noreferrer\">React 16.3</a> we introduced the official Context API as a replacement to the previous <a href=\"https://reactjs.org/docs/legacy-context.html\" rel=\"noopener noreferrer\">Legacy Context</a> API.</p>\n<div><pre><code><span>const</span> MyContext <span>=</span> React<span>.</span><span>createContext</span><span>(</span><span>)</span><span>;</span></code></pre></div>\n<p>We‚Äôve heard feedback that adopting the new render prop API can be difficult in class components. So we‚Äôve added a convenience API to <a href=\"https://reactjs.org/docs/context.html#classcontexttype\" rel=\"noopener noreferrer\">consume a context value from within a class component</a>.</p>\n<div><pre><code><span>class</span> <span>MyClass</span> <span>extends</span> <span>React<span>.</span>Component</span> <span>{</span>\n  <span>static</span> contextType <span>=</span> MyContext<span>;</span>\n  <span>componentDidMount</span><span>(</span><span>)</span> <span>{</span>\n    <span>let</span> value <span>=</span> <span>this</span><span>.</span>context<span>;</span>\n    <span>/* perform a side-effect at mount using the value of MyContext */</span>\n  <span>}</span>\n  <span>componentDidUpdate</span><span>(</span><span>)</span> <span>{</span>\n    <span>let</span> value <span>=</span> <span>this</span><span>.</span>context<span>;</span>\n    <span>/* ... */</span>\n  <span>}</span>\n  <span>componentWillUnmount</span><span>(</span><span>)</span> <span>{</span>\n    <span>let</span> value <span>=</span> <span>this</span><span>.</span>context<span>;</span>\n    <span>/* ... */</span>\n  <span>}</span>\n  <span>render</span><span>(</span><span>)</span> <span>{</span>\n    <span>let</span> value <span>=</span> <span>this</span><span>.</span>context<span>;</span>\n    <span>/* render something based on the value of MyContext */</span>\n  <span>}</span>\n<span>}</span></code></pre></div>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#static-getderivedstatefromerror\" rel=\"noopener noreferrer\"></a><a href=\"https://reactjs.org/docs/react-component.html#static-getderivedstatefromerror\" rel=\"noopener noreferrer\"><code>static getDerivedStateFromError()</code></a> </h2>\n<p>React 16 introduced <a href=\"https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html\" rel=\"noopener noreferrer\">Error Boundaries</a> for handling errors thrown in React renders. We already had the <code>componentDidCatch</code> lifecycle method which gets fired after an error has already happened. It‚Äôs great for logging errors to the server. It also lets you show a different UI to the user by calling <code>setState</code>.</p>\n<p>Before that is fired, we render <code>null</code> in place of the tree that threw an error. This sometimes breaks parent components that don‚Äôt expect their refs to be empty. It also doesn‚Äôt work to recover from errors on the server since the <code>Did</code> lifecycle methods don‚Äôt fire during server-side rendering.</p>\n<p>We‚Äôre adding another error method that lets you render the fallback UI before the render completes. See the docs for <a href=\"https://reactjs.org/docs/react-component.html#static-getderivedstatefromerror\" rel=\"noopener noreferrer\"><code>getDerivedStateFromError()</code></a>.</p>\n<blockquote>\n<p>Note: <code>getDerivedStateFromError()</code> is not yet available for server-side rendering. It is designed to work with server-side rendering in a future release. We‚Äôre releasing it early so that you can start preparing to use it.</p>\n</blockquote>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#deprecations-in-strictmode\" rel=\"noopener noreferrer\"></a>Deprecations in StrictMode </h2>\n<p>In <a href=\"https://reactjs.org/blog/2018/03/29/react-v-16-3.html#strictmode-component\" rel=\"noopener noreferrer\">16.3</a> we introduced the <a href=\"https://reactjs.org/docs/strict-mode.html\" rel=\"noopener noreferrer\"><code>StrictMode</code></a> component. It lets you opt-in to early warnings for patterns that might cause problems in the future.</p>\n<p>We‚Äôve added two more APIs to the list of deprecated APIs in <code>StrictMode</code>. If you don‚Äôt use <code>StrictMode</code> you don‚Äôt have to worry; these warning won‚Äôt fire for you.</p>\n<ul>\n<li><strong>ReactDOM.findDOMNode()</strong> - This API is often misunderstood and most uses of it are unnecessary. It can also be surprisingly slow in React 16. <a href=\"https://reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage\" rel=\"noopener noreferrer\">See the docs</a> for possible upgrade paths.</li>\n<li><strong>Legacy Context</strong> using contextTypes and getChildContext - Legacy context makes React slightly slower and bigger than it needs to be. That‚Äôs why we strongly want to encourage upgrading to the <a href=\"https://reactjs.org/docs/context.html\" rel=\"noopener noreferrer\">new context API</a>. Hopefully the addition of the <a href=\"https://reactjs.org/docs/context.html#classcontexttype\" rel=\"noopener noreferrer\"><code>contextType</code></a> API makes this a bit easier.</li>\n</ul>\n<p>If you‚Äôre having trouble upgrading, we‚Äôd like to hear your feedback.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#installation\" rel=\"noopener noreferrer\"></a>Installation </h2>\n<p>React v16.6.0 is available on the npm registry.</p>\n<p>To install React 16 with Yarn, run:</p>\n<div><pre><code>yarn add react@^16.6.0 react-dom@^16.6.0</code></pre></div>\n<p>To install React 16 with npm, run:</p>\n<div><pre><code><span>npm</span> <span>install</span> --save react@^16.6.0 react-dom@^16.6.0</code></pre></div>\n<p>We also provide UMD builds of React via a CDN:</p>\n<div><pre><code><span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react@16/umd/react.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span>\n<span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react-dom@16/umd/react-dom.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span></code></pre></div>\n<p>Refer to the documentation for <a href=\"https://reactjs.org/docs/installation.html\" rel=\"noopener noreferrer\">detailed installation instructions</a>.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#changelog\" rel=\"noopener noreferrer\"></a>Changelog </h2>\n<h3><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#react\" rel=\"noopener noreferrer\"></a>React </h3>\n<ul>\n<li>Add <code>React.memo()</code> as an alternative to <code>PureComponent</code> for functions. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/13748\" rel=\"noopener noreferrer\">#13748</a>)</li>\n<li>Add <code>React.lazy()</code> for code splitting components. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/13885\" rel=\"noopener noreferrer\">#13885</a>)</li>\n<li><code>React.StrictMode</code> now warns about legacy context API. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/13760\" rel=\"noopener noreferrer\">#13760</a>)</li>\n<li><code>React.StrictMode</code> now warns about <code>findDOMNode</code>. (<a href=\"https://github.com/sebmarkbage\" rel=\"noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/13841\" rel=\"noopener noreferrer\">#13841</a>)</li>\n<li>Rename <code>unstable_AsyncMode</code> to <code>unstable_ConcurrentMode</code>. (<a href=\"https://github.com/trueadm\" rel=\"noopener noreferrer\">@trueadm</a> in <a href=\"https://github.com/facebook/react/pull/13732\" rel=\"noopener noreferrer\">#13732</a>)</li>\n<li>Rename <code>unstable_Placeholder</code> to <code>Suspense</code>, and <code>delayMs</code> to <code>maxDuration</code>. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/13799\" rel=\"noopener noreferrer\">#13799</a> and <a href=\"https://github.com/sebmarkbage\" rel=\"noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/13922\" rel=\"noopener noreferrer\">#13922</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#react-dom\" rel=\"noopener noreferrer\"></a>React DOM </h3>\n<ul>\n<li>Add <code>contextType</code> as a more ergonomic way to subscribe to context from a class. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/13728\" rel=\"noopener noreferrer\">#13728</a>)</li>\n<li>Add <code>getDerivedStateFromError</code> lifecycle method for catching errors in a future asynchronous server-side renderer. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/13746\" rel=\"noopener noreferrer\">#13746</a>)</li>\n<li>Warn when <code>&lt;Context&gt;</code> is used instead of <code>&lt;Context.Consumer&gt;</code>. (<a href=\"https://github.com/trueadm\" rel=\"noopener noreferrer\">@trueadm</a> in <a href=\"https://github.com/facebook/react/pull/13829\" rel=\"noopener noreferrer\">#13829</a>)</li>\n<li>Fix gray overlay on iOS Safari. (<a href=\"https://github.com/philipp-spiess\" rel=\"noopener noreferrer\">@philipp-spiess</a> in <a href=\"https://github.com/facebook/react/pull/13778\" rel=\"noopener noreferrer\">#13778</a>)</li>\n<li>Fix a bug caused by overwriting <code>window.event</code> in development. (<a href=\"https://github.com/sergei-startsev\" rel=\"noopener noreferrer\">@sergei-startsev</a> in <a href=\"https://github.com/facebook/react/pull/13697\" rel=\"noopener noreferrer\">#13697</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#react-dom-server\" rel=\"noopener noreferrer\"></a>React DOM Server </h3>\n<ul>\n<li>Add support for <code>React.memo()</code>. (<a href=\"https://github.com/alexmckenley\" rel=\"noopener noreferrer\">@alexmckenley</a> in <a href=\"https://github.com/facebook/react/pull/13855\" rel=\"noopener noreferrer\">#13855</a>)</li>\n<li>Add support for <code>contextType</code>. (<a href=\"https://github.com/alexmckenley\" rel=\"noopener noreferrer\">@alexmckenley</a> and <a href=\"https://github.com/sebmarkbage\" rel=\"noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/13889\" rel=\"noopener noreferrer\">#13889</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html#scheduler-experimental\" rel=\"noopener noreferrer\"></a>Scheduler (Experimental) </h3>\n<ul>\n<li>Rename the package to <code>scheduler</code>. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/13683\" rel=\"noopener noreferrer\">#13683</a>)</li>\n<li>Support priority levels, continuations, and wrapped callbacks. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/13720\" rel=\"noopener noreferrer\">#13720</a> and <a href=\"https://github.com/facebook/react/pull/13842\" rel=\"noopener noreferrer\">#13842</a>)</li>\n<li>Improve the fallback mechanism in non-DOM environments. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/13740\" rel=\"noopener noreferrer\">#13740</a>)</li>\n<li>Schedule <code>requestAnimationFrame</code> earlier. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/13785\" rel=\"noopener noreferrer\">#13785</a>)</li>\n<li>Fix the DOM detection to be more thorough. (<a href=\"https://github.com/trueadm\" rel=\"noopener noreferrer\">@trueadm</a> in <a href=\"https://github.com/facebook/react/pull/13731\" rel=\"noopener noreferrer\">#13731</a>)</li>\n<li>Fix bugs with interaction tracing. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/13590\" rel=\"noopener noreferrer\">#13590</a>)</li>\n<li>Add the <code>envify</code> transform to the package. (<a href=\"https://github.com/mridgway\" rel=\"noopener noreferrer\">@mridgway</a> in <a href=\"https://github.com/facebook/react/pull/13766\" rel=\"noopener noreferrer\">#13766</a>)</li>\n</ul>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2018/11/13/react-conf-recap.html",
        link: "https://reactjs.org/blog/2018/11/13/react-conf-recap.html",
        title: "React Conf recap: Hooks, Suspense, and Concurrent Rendering",
        date: 2018-11-13T00:00:00Z,
        summary: Some(
            "This year‚Äôs React Conf took place on October 25 and 26 in Henderson, Nevada, where more than 600 attendees gathered to discuss the latest in UI engineering.\n\n\n          \n            \n          \n          \nSophie Alpert and Dan Abramov kicked off Day 1 with their keynote, React Today and Tomorrow. In the talk, they introduced Hooks, which are a new proposal that adds the ability to access features such as state without writing a JavaScript class. Hooks promise to dramatically simplify the code required for React components and are currently available in a React alpha release.\n\n\n          \n            \n          \n          \nOn the morning of Day 2, Andrew Clark and Brian Vaughn presented Concurrent Rendering in React. Andrew covered the recently announced React.lazy API for code splitting and previewed two upcoming features: concurrent mode and Suspense. Brian demonstrated how to use React‚Äôs new profiler tooling to make apps built in React run faster.\n\n\n          \n            \n          \n          \nIn the afternoon, Parashuram N spoke in detail about React Native‚Äôs New Architecture, a long-term project that the React Native team has been working on over the past year and announced in June. We‚Äôre really excited about the potential of this project to improve performance, simplify interoperability with other libraries, and set a strong foundation for the future of React Native.\nNow that the conference is over, all 28 conference talks are available to stream online. There are tons of great ones from both days. We can‚Äôt wait until next year!",
        ),
        content: Some(
            "<p>This year‚Äôs <a href=\"https://conf.reactjs.org/\" rel=\"noopener noreferrer\">React Conf</a> took place on October 25 and 26 in Henderson, Nevada, where more than 600 attendees gathered to discuss the latest in UI engineering.</p>\n<br>\n<div>\n          <div>\n            \n          </div>\n          </div>\n<p>Sophie Alpert and Dan Abramov kicked off Day 1 with their keynote, React Today and Tomorrow. In the talk, they introduced <a href=\"https://reactjs.org/docs/hooks-intro.html\" rel=\"noopener noreferrer\">Hooks</a>, which are a new proposal that adds the ability to access features such as state without writing a JavaScript class. Hooks promise to dramatically simplify the code required for React components and are currently available in a React alpha release.</p>\n<br>\n<div>\n          <div>\n            \n          </div>\n          </div>\n<p>On the morning of Day 2, Andrew Clark and Brian Vaughn presented Concurrent Rendering in React. Andrew covered the recently announced <a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html\" rel=\"noopener noreferrer\">React.lazy API for code splitting</a> and previewed two upcoming features: concurrent mode and Suspense. Brian demonstrated how to use <a href=\"https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html\" rel=\"noopener noreferrer\">React‚Äôs new profiler</a> tooling to make apps built in React run faster.</p>\n<br>\n<div>\n          <div>\n            \n          </div>\n          </div>\n<p>In the afternoon, Parashuram N spoke in detail about React Native‚Äôs New Architecture, a long-term project that the React Native team has been working on over the past year and <a href=\"https://facebook.github.io/react-native/blog/2018/06/14/state-of-react-native-2018\" rel=\"noopener noreferrer\">announced in June</a>. We‚Äôre really excited about the potential of this project to improve performance, simplify interoperability with other libraries, and set a strong foundation for the future of React Native.</p>\n<p>Now that the conference is over, all 28 conference talks are <a href=\"https://www.youtube.com/playlist?list=PLPxbbTqCLbGE5AihOSExAa4wUM-P42EIJ\" rel=\"noopener noreferrer\">available to stream online</a>. There are tons of great ones from both days. We can‚Äôt wait until next year!</p>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2018/11/27/react-16-roadmap.html",
        link: "https://reactjs.org/blog/2018/11/27/react-16-roadmap.html",
        title: "React 16.x Roadmap",
        date: 2018-11-27T00:00:00Z,
        summary: Some(
            "You might have heard about features like ‚ÄúHooks‚Äù, ‚ÄúSuspense‚Äù, and ‚ÄúConcurrent Rendering‚Äù in the previous blog posts and talks. In this post, we‚Äôll look at how they fit together and the expected timeline for their availability in a stable release of React.\n\nAn Update from August, 2019\nYou can find an update to this roadmap in the React 16.9 release blog post.\n\ntl;dr \nWe plan to split the rollout of new React features into the following milestones:\n\nReact 16.6 with Suspense for Code Splitting (already shipped)\nA minor 16.x release with React Hooks (~Q1 2019)\nA minor 16.x release with Concurrent Mode (~Q2 2019)\nA minor 16.x release with Suspense for Data Fetching (~mid 2019)\n\n(The original version of this post used exact version numbers. We edited it to reflect that there might need to be a few other minor releases in the middle between these ones.)\nThese are estimates, and the details may change as we‚Äôre further along. There‚Äôs at least two more projects we plan to complete in 2019. They require more exploration and aren‚Äôt tied to a particular release yet:\n\nModernizing React DOM\nSuspense for Server Rendering\n\nWe expect to get more clarity on their timeline in the coming months.\n\nNote\nThis post is just a roadmap ‚Äî there is nothing in it that requires your immediate attention. When each of these features are released, we‚Äôll publish a full blog post announcing them.\n\nRelease Timeline \nWe have a single vision for how all of these features fit together, but we‚Äôre releasing each part as soon as it is ready so that you can test and start using them sooner. The API design doesn‚Äôt always make sense when looking at one piece in isolation; this post lays out the major parts of our plan to help you see the whole picture. (See our versioning policy to learn more about our commitment to stability.)\nThe gradual release strategy helps us refine the APIs, but the transitional period when some things aren‚Äôt ready can be confusing. Let‚Äôs look at what these different features mean for your app, how they relate to each other, and when you can expect to start learning and using them.\nReact 16.6 (shipped): The One with Suspense for Code Splitting \nSuspense refers to React‚Äôs new ability to ‚Äúsuspend‚Äù rendering while components are waiting for something, and display a loading indicator. In React 16.6, Suspense supports only one use case: lazy loading components with React.lazy() and &lt;React.Suspense&gt;.\n// This component is loaded dynamically\nconst OtherComponent = React.lazy(() =&gt; import(\'./OtherComponent\'));\n\nfunction MyComponent() {\n  return (\n    &lt;React.Suspense fallback={&lt;Spinner /&gt;}&gt;\n      &lt;div&gt;\n        &lt;OtherComponent /&gt;\n      &lt;/div&gt;\n    &lt;/React.Suspense&gt;\n  );\n}\nCode splitting with React.lazy() with &lt;React.Suspense&gt; is documented in the Code Splitting guide. You can find another practical explanation in this article.\nWe have been using Suspense for code splitting at Facebook since July, and expect it to be stable. There‚Äôs been a few regressions in the initial public release in 16.6.0, but they were fixed in 16.6.3.\nCode splitting is just the first step for Suspense. Our longer term vision for Suspense involves letting it handle data fetching too (and integrate with libraries like Apollo). In addition to a convenient programming model, Suspense also provides better user experience in Concurrent Mode. You‚Äôll find information about these topics further below.\nStatus in React DOM: Available since React 16.6.0.\nStatus in React DOM Server: Suspense is not available in the server renderer yet. This isn‚Äôt for the lack of attention. We‚Äôve started work on a new asynchronous server renderer that will support Suspense, but it‚Äôs a large project and will take a good chunk of 2019 to complete.\nStatus in React Native: Bundle splitting isn‚Äôt very useful in React Native, but there‚Äôs nothing technically preventing React.lazy() and &lt;Suspense&gt; from working when given a Promise to a module.\nRecommendation: If you only do client rendering, we recommend widely adopting React.lazy() and &lt;React.Suspense&gt; for code splitting React components. If you do server rendering, you‚Äôll have to wait with adoption until the new server renderer is ready.\nReact 16.x (~Q1 2019): The One with Hooks \nHooks let you use features like state and lifecycle from function components. They also let you reuse stateful logic between components without introducing extra nesting in your tree.\nfunction Example() {\n  // Declare a new state variable, which we\'ll call \"count\"\n  const [count, setCount] = useState(0);\n\n  return (\n   &lt;div&gt;\n     &lt;p&gt;You clicked {count} times&lt;/p&gt;\n     &lt;button onClick={() =&gt; setCount(count + 1)}&gt;\n       Click me\n     &lt;/button&gt;\n   &lt;/div&gt;\n );\n}\nHooks introduction and overview are good places to start. Watch these talks for a video introduction and a deep dive. The FAQ should answer most of your further questions. To learn more about the motivation behind Hooks, you can read this article. Some of the rationale for the API design of Hooks is explained in this RFC thread reply.\nWe have been dogfooding Hooks at Facebook since September. We don‚Äôt expect major bugs in the implementation. Hooks are only available in the 16.7 alpha versions of React. Some of their API is expected to change in the final version (see the end of this comment for details). It is possible that the minor release with Hooks might not be React 16.7.\nHooks represent our vision for the future of React. They solve both problems that React users experience directly (‚Äúwrapper hell‚Äù of render props and higher-order components, duplication of logic in lifecycle methods), and the issues we‚Äôve encountered optimizing React at scale (such as difficulties in inlining components with a compiler). Hooks don‚Äôt deprecate classes. However, if Hooks are successful, it is possible that in a future major release class support might move to a separate package, reducing the default bundle size of React.\nStatus in React DOM: The first version of react and react-dom supporting Hooks is 16.7.0-alpha.0. We expect to publish more alphas over the next months (at the time of writing, the latest one is 16.7.0-alpha.2). You can try them by installing react@next with react-dom@next. Don‚Äôt forget to update react-dom ‚Äî otherwise Hooks won‚Äôt work.\nStatus in React DOM Server: The same 16.7 alpha versions of react-dom fully support Hooks with react-dom/server.\nStatus in React Native: There is no officially supported way to try Hooks in React Native yet. If you‚Äôre feeling adventurous, check out this thread for unofficial instructions. There is a known issue with useEffect firing too late which still needs to be solved.\nRecommendation: When you‚Äôre ready, we encourage you to start trying Hooks in new components you write. Make sure everyone on your team is on board with using them and familiar with this documentation. We don‚Äôt recommend rewriting your existing classes to Hooks unless you planned to rewrite them anyway (e.g. to fix bugs). Read more about the adoption strategy here.\nReact 16.x (~Q2 2019): The One with Concurrent Mode \nConcurrent Mode lets React apps be more responsive by rendering component trees without blocking the main thread. It is opt-in and allows React to interrupt a long-running render (for example, rendering a new feed story) to handle a high-priority event (for example, text input or hover). Concurrent Mode also improves the user experience of Suspense by skipping unnecessary loading states on fast connections.\n\nNote\nYou might have previously heard Concurrent Mode being referred to as ‚Äúasync mode‚Äù. We‚Äôve changed the name to Concurrent Mode to highlight React‚Äôs ability to perform work on different priority levels. This sets it apart from other approaches to async rendering.\n\n// Two ways to opt in:\n\n// 1. Part of an app (not final API)\n&lt;React.unstable_ConcurrentMode&gt;\n  &lt;Something /&gt;\n&lt;/React.unstable_ConcurrentMode&gt;\n\n// 2. Whole app (not final API)\nReactDOM.unstable_createRoot(domNode).render(&lt;App /&gt;);\nThere is no documentation written for the Concurrent Mode yet. It is important to highlight that the conceptual model will likely be unfamiliar at first. Documenting its benefits, how to use it efficiently, and its pitfalls is a high priority for us, and will be a prerequisite for calling it stable. Until then, Andrew‚Äôs talk is the best introduction available.\nConcurrent Mode is much less polished than Hooks. Some APIs aren‚Äôt properly ‚Äúwired up‚Äù yet and don‚Äôt do what they‚Äôre expected to. At the time of writing this post, we don‚Äôt recommend using it for anything except very early experimentation. We don‚Äôt expect many bugs in Concurrent Mode itself, but note that components that produce warnings in &lt;React.StrictMode&gt; may not work correctly. On a separate note, we‚Äôve seen that Concurrent Mode surfaces performance problems in other code which can sometimes be mistaken for performance issues in Concurrent Mode itself. For example, a stray setInterval(fn, 1) call that runs every millisecond would have a worse effect in Concurrent Mode. We plan to publish more guidance about diagnosing and fixing issues like this as part of this release‚Äôs documentation.\nConcurrent Mode is a big part of our vision for React. For CPU-bound work, it allows non-blocking rendering and keeps your app responsive while rendering complex component trees. That‚Äôs demoed in the first part of our JSConf Iceland talk. Concurrent Mode also makes Suspense better. It lets you avoid flickering a loading indicator if the network is fast enough. It‚Äôs hard to explain without seeing so Andrew‚Äôs talk is the best resource available today. Concurrent Mode relies on a cooperative main thread scheduler, and we are collaborating with the Chrome team to eventually move this functionality into the browser itself.\nStatus in React DOM: A very unstable version of Concurrent Mode is available behind an unstable_ prefix in React 16.6 but we don‚Äôt recommend trying it unless you‚Äôre willing to often run into walls or missing features. The 16.7 alphas include React.ConcurrentMode and ReactDOM.createRoot without an unstable_ prefix, but we‚Äôll likely keep the prefix in 16.7, and only document and mark Concurrent Mode as stable in this future minor release.\nStatus in React DOM Server: Concurrent Mode doesn‚Äôt directly affect server rendering. It will work with the existing server renderer.\nStatus in React Native: The current plan is to delay enabling Concurrent Mode in React Native until React Fabric project is near completion.\nRecommendation: If you wish to adopt Concurrent Mode in the future, wrapping some component subtrees in &lt;React.StrictMode&gt; and fixing the resulting warnings is a good first step. In general it‚Äôs not expected that legacy code would immediately be compatible. For example, at Facebook we mostly intend to use the Concurrent Mode in the more recently developed codebases, and keep the legacy ones running in the synchronous mode for the near future.\nReact 16.x (~mid 2019): The One with Suspense for Data Fetching \nAs mentioned earlier, Suspense refers to React‚Äôs ability to ‚Äúsuspend‚Äù rendering while components are waiting for something, and display a loading indicator. In the already shipped React 16.6, the only supported use case for Suspense is code splitting. In this future minor release, we‚Äôd like to provide officially supported ways to use it for data fetching too. We‚Äôll provide a reference implementation of a basic ‚ÄúReact Cache‚Äù that‚Äôs compatible with Suspense, but you can also write your own. Data fetching libraries like Apollo and Relay will be able to integrate with Suspense by following a simple specification that we‚Äôll document.\n// React Cache for simple data fetching (not final API)\nimport {unstable_createResource} from \'react-cache\';\n\n// Tell React Cache how to fetch your data\nconst TodoResource = unstable_createResource(fetchTodo);\n\nfunction Todo(props) {\n  // Suspends until the data is in the cache\n  const todo = TodoResource.read(props.id);\n  return &lt;li&gt;{todo.title}&lt;/li&gt;;\n}\n\nfunction App() {\n  return (\n    // Same Suspense component you already use for code splitting\n    // would be able to handle data fetching too.\n    &lt;React.Suspense fallback={&lt;Spinner /&gt;}&gt;\n      &lt;ul&gt;\n        {/* Siblings fetch in parallel */}\n        &lt;Todo id=\"1\" /&gt;\n        &lt;Todo id=\"2\" /&gt;\n      &lt;/ul&gt;\n    &lt;/React.Suspense&gt;\n  );\n}\n\n// Other libraries like Apollo and Relay can also\n// provide Suspense integrations with similar APIs.\nThere is no official documentation for how to fetch data with Suspense yet, but you can find some early information in this talk and this small demo. We‚Äôll write documentation for React Cache (and how to write your own Suspense-compatible library) closer to this React release, but if you‚Äôre curious, you can find its very early source code here.\nThe low-level Suspense mechanism (suspending rendering and showing a fallback) is expected to be stable even in React 16.6. We‚Äôve used it for code splitting in production for months. However, the higher-level APIs for data fetching are very unstable. React Cache is rapidly changing, and will change at least a few more times. There are some low-level APIs that are missing for a good higher-level API to be possible. We don‚Äôt recommend using React Cache anywhere except very early experiments. Note that React Cache itself isn‚Äôt strictly tied to React releases, but the current alphas lack basic features as cache invalidation, and you‚Äôll run into a wall very soon. We expect to have something usable with this React release.\nEventually we‚Äôd like most data fetching to happen through Suspense but it will take a long time until all integrations are ready. In practice we expect it to be adopted very incrementally, and often through layers like Apollo or Relay rather than directly. Missing higher level APIs aren‚Äôt the only obstacle ‚Äî there are also some important UI patterns we don‚Äôt support yet such as showing progress indicator outside of the loading view hierarchy. As always, we will communicate our progress in the release notes on this blog.\nStatus in React DOM and React Native: Technically, a compatible cache would already work with &lt;React.Suspense&gt; in React 16.6. However, we don‚Äôt expect to have a good cache implementation until this React minor release. If you‚Äôre feeling adventurous, you can try to write your own cache by looking at the React Cache alphas. However, note that the mental model is sufficiently different that there‚Äôs a high risk of misunderstanding it until the docs are ready.\nStatus in React DOM Server: Suspense is not available in the server renderer yet. As we mentioned earlier, we‚Äôve started work on a new asynchronous server renderer that will support Suspense, but it‚Äôs a large project and will take a good chunk of 2019 to complete.\nRecommendation: Wait for this minor React release in order to use Suspense for data fetching. Don‚Äôt try to use Suspense features in 16.6 for it; it‚Äôs not supported. However, your existing &lt;Suspense&gt; components for code splitting will be able to show loading states for data too when Suspense for Data Fetching becomes officially supported.\nOther Projects \nModernizing React DOM \nWe started an investigation into simplifying and modernizing ReactDOM, with a goal of reduced bundle size and aligning closer with the browser behavior. It is still early to say which specific bullet points will ‚Äúmake it‚Äù because the project is in an exploratory phase. We will communicate our progress on that issue.\nSuspense for Server Rendering \nWe started designing a new server renderer that supports Suspense (including waiting for asynchronous data on the server without double rendering) and progressively loading and hydrating page content in chunks for best user experience. You can watch an overview of its early prototype in this talk. The new server renderer is going to be our major focus in 2019, but it‚Äôs too early to say anything about its release schedule. Its development, as always, will happen on GitHub.\n\nAnd that‚Äôs about it! As you can see, there‚Äôs a lot here to keep us busy but we expect much progress in the coming months.\nWe hope this post gives you an idea of what we‚Äôre working on, what you can use today, and what you can expect to use in the future. While there‚Äôs a lot of discussion about new features on social media platforms, you won‚Äôt miss anything important if you read this blog.\nWe‚Äôre always open to feedback, and love to hear from you in the RFC repository, the issue tracker, and on Twitter.",
        ),
        content: Some(
            "<p>You might have heard about features like ‚ÄúHooks‚Äù, ‚ÄúSuspense‚Äù, and ‚ÄúConcurrent Rendering‚Äù in the previous blog posts and talks. In this post, we‚Äôll look at how they fit together and the expected timeline for their availability in a stable release of React.</p>\n<blockquote>\n<p>An Update from August, 2019</p>\n<p>You can find an update to this roadmap in the <a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an-update-to-the-roadmap\" rel=\"noopener noreferrer\">React 16.9 release blog post</a>.</p>\n</blockquote>\n<h2><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#tldr\" rel=\"noopener noreferrer\"></a>tl;dr </h2>\n<p>We plan to split the rollout of new React features into the following milestones:</p>\n<ul>\n<li>React 16.6 with <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-166-shipped-the-one-with-suspense-for-code-splitting\" rel=\"noopener noreferrer\">Suspense for Code Splitting</a> (<em>already shipped</em>)</li>\n<li>A minor 16.x release with <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-q1-2019-the-one-with-hooks\" rel=\"noopener noreferrer\">React Hooks</a> (~Q1 2019)</li>\n<li>A minor 16.x release with <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-q2-2019-the-one-with-concurrent-mode\" rel=\"noopener noreferrer\">Concurrent Mode</a> (~Q2 2019)</li>\n<li>A minor 16.x release with <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-mid-2019-the-one-with-suspense-for-data-fetching\" rel=\"noopener noreferrer\">Suspense for Data Fetching</a> (~mid 2019)</li>\n</ul>\n<p><em>(The original version of this post used exact version numbers. We edited it to reflect that there might need to be a few other minor releases in the middle between these ones.)</em></p>\n<p>These are estimates, and the details may change as we‚Äôre further along. There‚Äôs at least two more projects we plan to complete in 2019. They require more exploration and aren‚Äôt tied to a particular release yet:</p>\n<ul>\n<li><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#modernizing-react-dom\" rel=\"noopener noreferrer\">Modernizing React DOM</a></li>\n<li><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#suspense-for-server-rendering\" rel=\"noopener noreferrer\">Suspense for Server Rendering</a></li>\n</ul>\n<p>We expect to get more clarity on their timeline in the coming months.</p>\n<blockquote>\n<p>Note</p>\n<p>This post is just a roadmap ‚Äî there is nothing in it that requires your immediate attention. When each of these features are released, we‚Äôll publish a full blog post announcing them.</p>\n</blockquote>\n<h2><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#release-timeline\" rel=\"noopener noreferrer\"></a>Release Timeline </h2>\n<p>We have a single vision for how all of these features fit together, but we‚Äôre releasing each part as soon as it is ready so that you can test and start using them sooner. The API design doesn‚Äôt always make sense when looking at one piece in isolation; this post lays out the major parts of our plan to help you see the whole picture. (See our <a href=\"https://reactjs.org/docs/faq-versioning.html\" rel=\"noopener noreferrer\">versioning policy</a> to learn more about our commitment to stability.)</p>\n<p>The gradual release strategy helps us refine the APIs, but the transitional period when some things aren‚Äôt ready can be confusing. Let‚Äôs look at what these different features mean for your app, how they relate to each other, and when you can expect to start learning and using them.</p>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-166-shipped-the-one-with-suspense-for-code-splitting\" rel=\"noopener noreferrer\"></a><a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html\" rel=\"noopener noreferrer\">React 16.6</a> (shipped): The One with Suspense for Code Splitting </h3>\n<p><em>Suspense</em> refers to React‚Äôs new ability to ‚Äúsuspend‚Äù rendering while components are waiting for something, and display a loading indicator. In React 16.6, Suspense supports only one use case: lazy loading components with <code>React.lazy()</code> and <code>&lt;React.Suspense&gt;</code>.</p>\n<div><pre><code><span>// This component is loaded dynamically</span>\n<span>const</span> OtherComponent <span>=</span> React<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>import</span><span>(</span><span>\'./OtherComponent\'</span><span>)</span><span>)</span><span>;</span>\n\n<span>function</span> <span>MyComponent</span><span>(</span><span>)</span> <span>{</span>\n  <span>return</span> <span>(</span>\n    <span><span><span>&lt;</span>React.Suspense</span> <span>fallback</span><span><span>=</span><span>{</span><span><span><span>&lt;</span>Spinner</span> <span>/&gt;</span></span><span>}</span></span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>div</span><span>&gt;</span></span><span>\n        </span><span><span><span>&lt;</span>OtherComponent</span> <span>/&gt;</span></span><span>\n      </span><span><span><span>&lt;/</span>div</span><span>&gt;</span></span><span>\n    </span><span><span><span>&lt;/</span>React.Suspense</span><span>&gt;</span></span>\n  <span>)</span><span>;</span>\n<span>}</span></code></pre></div>\n<p>Code splitting with <code>React.lazy()</code> with <code>&lt;React.Suspense&gt;</code> is documented <a href=\"https://reactjs.org/docs/code-splitting.html#reactlazy\" rel=\"noopener noreferrer\">in the Code Splitting guide</a>. You can find another practical explanation in <a href=\"https://medium.com/@pomber/lazy-loading-and-preloading-components-in-react-16-6-804de091c82d\" rel=\"noopener noreferrer\">this article</a>.</p>\n<p>We have been using Suspense for code splitting at Facebook since July, and expect it to be stable. There‚Äôs been a few regressions in the initial public release in 16.6.0, but they were fixed in 16.6.3.</p>\n<p>Code splitting is just the first step for Suspense. Our longer term vision for Suspense involves letting it handle data fetching too (and integrate with libraries like Apollo). In addition to a convenient programming model, Suspense also provides better user experience in Concurrent Mode. You‚Äôll find information about these topics further below.</p>\n<p><strong>Status in React DOM:</strong> Available since React 16.6.0.</p>\n<p><strong>Status in React DOM Server:</strong> Suspense is not available in the server renderer yet. This isn‚Äôt for the lack of attention. We‚Äôve started work on a new asynchronous server renderer that will support Suspense, but it‚Äôs a large project and will take a good chunk of 2019 to complete.</p>\n<p><strong>Status in React Native:</strong> Bundle splitting isn‚Äôt very useful in React Native, but there‚Äôs nothing technically preventing <code>React.lazy()</code> and <code>&lt;Suspense&gt;</code> from working when given a Promise to a module.</p>\n<p><strong>Recommendation:</strong> If you only do client rendering, we recommend widely adopting <code>React.lazy()</code> and <code>&lt;React.Suspense&gt;</code> for code splitting React components. If you do server rendering, you‚Äôll have to wait with adoption until the new server renderer is ready.</p>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-q1-2019-the-one-with-hooks\" rel=\"noopener noreferrer\"></a>React 16.x (~Q1 2019): The One with Hooks </h3>\n<p><em>Hooks</em> let you use features like state and lifecycle from function components. They also let you reuse stateful logic between components without introducing extra nesting in your tree.</p>\n<div><pre><code><span>function</span> <span>Example</span><span>(</span><span>)</span> <span>{</span>\n  <span>// Declare a new state variable, which we\'ll call \"count\"</span>\n  <span>const</span> <span>[</span>count<span>,</span> setCount<span>]</span> <span>=</span> <span>useState</span><span>(</span><span>0</span><span>)</span><span>;</span>\n\n  <span>return</span> <span>(</span>\n   <span><span><span>&lt;</span>div</span><span>&gt;</span></span><span>\n     </span><span><span><span>&lt;</span>p</span><span>&gt;</span></span><span>You clicked </span><span>{</span>count<span>}</span><span> times</span><span><span><span>&lt;/</span>p</span><span>&gt;</span></span><span>\n     </span><span><span><span>&lt;</span>button</span> <span>onClick</span><span><span>=</span><span>{</span><span>(</span><span>)</span> <span>=&gt;</span> <span>setCount</span><span>(</span>count <span>+</span> <span>1</span><span>)</span><span>}</span></span><span>&gt;</span></span><span>\n       Click me\n     </span><span><span><span>&lt;/</span>button</span><span>&gt;</span></span><span>\n   </span><span><span><span>&lt;/</span>div</span><span>&gt;</span></span>\n <span>)</span><span>;</span>\n<span>}</span></code></pre></div>\n<p>Hooks <a href=\"https://reactjs.org/docs/hooks-intro.html\" rel=\"noopener noreferrer\">introduction</a> and <a href=\"https://reactjs.org/docs/hooks-overview.html\" rel=\"noopener noreferrer\">overview</a> are good places to start. Watch <a href=\"https://www.youtube.com/watch?v=V-QO-KO90iQ\" rel=\"noopener noreferrer\">these talks</a> for a video introduction and a deep dive. The <a href=\"https://reactjs.org/docs/hooks-faq.html\" rel=\"noopener noreferrer\">FAQ</a> should answer most of your further questions. To learn more about the motivation behind Hooks, you can read <a href=\"https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889\" rel=\"noopener noreferrer\">this article</a>. Some of the rationale for the API design of Hooks is explained in <a href=\"https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884\" rel=\"noopener noreferrer\">this RFC thread reply</a>.</p>\n<p>We have been dogfooding Hooks at Facebook since September. We don‚Äôt expect major bugs in the implementation. Hooks are only available in the 16.7 alpha versions of React. Some of their API is expected to change in the final version (see the end of <a href=\"https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884\" rel=\"noopener noreferrer\">this comment</a> for details). It is possible that the minor release with Hooks might not be React 16.7.</p>\n<p>Hooks represent our vision for the future of React. They solve both problems that React users experience directly (‚Äúwrapper hell‚Äù of render props and higher-order components, duplication of logic in lifecycle methods), and the issues we‚Äôve encountered optimizing React at scale (such as difficulties in inlining components with a compiler). Hooks don‚Äôt deprecate classes. However, if Hooks are successful, it is possible that in a future <em>major</em> release class support might move to a separate package, reducing the default bundle size of React.</p>\n<p><strong>Status in React DOM:</strong> The first version of <code>react</code> and <code>react-dom</code> supporting Hooks is <code>16.7.0-alpha.0</code>. We expect to publish more alphas over the next months (at the time of writing, the latest one is <code>16.7.0-alpha.2</code>). You can try them by installing <code>react@next</code> with <code>react-dom@next</code>. Don‚Äôt forget to update <code>react-dom</code> ‚Äî otherwise Hooks won‚Äôt work.</p>\n<p><strong>Status in React DOM Server:</strong> The same 16.7 alpha versions of <code>react-dom</code> fully support Hooks with <code>react-dom/server</code>.</p>\n<p><strong>Status in React Native:</strong> There is no officially supported way to try Hooks in React Native yet. If you‚Äôre feeling adventurous, check out <a href=\"https://github.com/facebook/react-native/issues/21967\" rel=\"noopener noreferrer\">this thread</a> for unofficial instructions. There is a known issue with <code>useEffect</code> firing too late which still needs to be solved.</p>\n<p><strong>Recommendation:</strong> When you‚Äôre ready, we encourage you to start trying Hooks in new components you write. Make sure everyone on your team is on board with using them and familiar with this documentation. We don‚Äôt recommend rewriting your existing classes to Hooks unless you planned to rewrite them anyway (e.g. to fix bugs). Read more about the adoption strategy <a href=\"https://reactjs.org/docs/hooks-faq.html#adoption-strategy\" rel=\"noopener noreferrer\">here</a>.</p>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-q2-2019-the-one-with-concurrent-mode\" rel=\"noopener noreferrer\"></a>React 16.x (~Q2 2019): The One with Concurrent Mode </h3>\n<p><em>Concurrent Mode</em> lets React apps be more responsive by rendering component trees without blocking the main thread. It is opt-in and allows React to interrupt a long-running render (for example, rendering a new feed story) to handle a high-priority event (for example, text input or hover). Concurrent Mode also improves the user experience of Suspense by skipping unnecessary loading states on fast connections.</p>\n<blockquote>\n<p>Note</p>\n<p>You might have previously heard Concurrent Mode being referred to as <a href=\"https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html\" rel=\"noopener noreferrer\">‚Äúasync mode‚Äù</a>. We‚Äôve changed the name to Concurrent Mode to highlight React‚Äôs ability to perform work on different priority levels. This sets it apart from other approaches to async rendering.</p>\n</blockquote>\n<div><pre><code><span>// Two ways to opt in:</span>\n\n<span>// 1. Part of an app (not final API)</span>\n<span><span><span>&lt;</span>React.unstable_ConcurrentMode</span><span>&gt;</span></span><span>\n  </span><span><span><span>&lt;</span>Something</span> <span>/&gt;</span></span><span>\n</span><span><span><span>&lt;/</span>React.unstable_ConcurrentMode</span><span>&gt;</span></span>\n\n<span>// 2. Whole app (not final API)</span>\nReactDOM<span>.</span><span>unstable_createRoot</span><span>(</span>domNode<span>)</span><span>.</span><span>render</span><span>(</span><span><span><span>&lt;</span>App</span> <span>/&gt;</span></span><span>)</span><span>;</span></code></pre></div>\n<p>There is no documentation written for the Concurrent Mode yet. It is important to highlight that the conceptual model will likely be unfamiliar at first. Documenting its benefits, how to use it efficiently, and its pitfalls is a high priority for us, and will be a prerequisite for calling it stable. Until then, <a href=\"https://www.youtube.com/watch?v=ByBPyMBTzM0\" rel=\"noopener noreferrer\">Andrew‚Äôs talk</a> is the best introduction available.</p>\n<p>Concurrent Mode is <em>much</em> less polished than Hooks. Some APIs aren‚Äôt properly ‚Äúwired up‚Äù yet and don‚Äôt do what they‚Äôre expected to. At the time of writing this post, we don‚Äôt recommend using it for anything except very early experimentation. We don‚Äôt expect many bugs in Concurrent Mode itself, but note that components that produce warnings in <a href=\"https://reactjs.org/docs/strict-mode.html\" rel=\"noopener noreferrer\"><code>&lt;React.StrictMode&gt;</code></a> may not work correctly. On a separate note, we‚Äôve seen that Concurrent Mode <em>surfaces</em> performance problems in other code which can sometimes be mistaken for performance issues in Concurrent Mode itself. For example, a stray <code>setInterval(fn, 1)</code> call that runs every millisecond would have a worse effect in Concurrent Mode. We plan to publish more guidance about diagnosing and fixing issues like this as part of this release‚Äôs documentation.</p>\n<p>Concurrent Mode is a big part of our vision for React. For CPU-bound work, it allows non-blocking rendering and keeps your app responsive while rendering complex component trees. That‚Äôs demoed in the first part of <a href=\"https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html\" rel=\"noopener noreferrer\">our JSConf Iceland talk</a>. Concurrent Mode also makes Suspense better. It lets you avoid flickering a loading indicator if the network is fast enough. It‚Äôs hard to explain without seeing so <a href=\"https://www.youtube.com/watch?v=ByBPyMBTzM0\" rel=\"noopener noreferrer\">Andrew‚Äôs talk</a> is the best resource available today. Concurrent Mode relies on a cooperative main thread <a href=\"https://github.com/facebook/react/tree/master/packages/scheduler\" rel=\"noopener noreferrer\">scheduler</a>, and we are <a href=\"https://www.youtube.com/watch?v=mDdgfyRB5kg\" rel=\"noopener noreferrer\">collaborating with the Chrome team</a> to eventually move this functionality into the browser itself.</p>\n<p><strong>Status in React DOM:</strong> A <em>very</em> unstable version of Concurrent Mode is available behind an <code>unstable_</code> prefix in React 16.6 but we don‚Äôt recommend trying it unless you‚Äôre willing to often run into walls or missing features. The 16.7 alphas include <code>React.ConcurrentMode</code> and <code>ReactDOM.createRoot</code> without an <code>unstable_</code> prefix, but we‚Äôll likely keep the prefix in 16.7, and only document and mark Concurrent Mode as stable in this future minor release.</p>\n<p><strong>Status in React DOM Server:</strong> Concurrent Mode doesn‚Äôt directly affect server rendering. It will work with the existing server renderer.</p>\n<p><strong>Status in React Native:</strong> The current plan is to delay enabling Concurrent Mode in React Native until <a href=\"https://github.com/react-native-community/discussions-and-proposals/issues/4\" rel=\"noopener noreferrer\">React Fabric</a> project is near completion.</p>\n<p><strong>Recommendation:</strong> If you wish to adopt Concurrent Mode in the future, wrapping some component subtrees in <a href=\"https://reactjs.org/docs/strict-mode.html\" rel=\"noopener noreferrer\"><code>&lt;React.StrictMode&gt;</code></a> and fixing the resulting warnings is a good first step. In general it‚Äôs not expected that legacy code would immediately be compatible. For example, at Facebook we mostly intend to use the Concurrent Mode in the more recently developed codebases, and keep the legacy ones running in the synchronous mode for the near future.</p>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-mid-2019-the-one-with-suspense-for-data-fetching\" rel=\"noopener noreferrer\"></a>React 16.x (~mid 2019): The One with Suspense for Data Fetching </h3>\n<p>As mentioned earlier, <em>Suspense</em> refers to React‚Äôs ability to ‚Äúsuspend‚Äù rendering while components are waiting for something, and display a loading indicator. In the already shipped React 16.6, the only supported use case for Suspense is code splitting. In this future minor release, we‚Äôd like to provide officially supported ways to use it for data fetching too. We‚Äôll provide a reference implementation of a basic ‚ÄúReact Cache‚Äù that‚Äôs compatible with Suspense, but you can also write your own. Data fetching libraries like Apollo and Relay will be able to integrate with Suspense by following a simple specification that we‚Äôll document.</p>\n<div><pre><code><span>// React Cache for simple data fetching (not final API)</span>\n<span>import</span> <span>{</span>unstable_createResource<span>}</span> <span>from</span> <span>\'react-cache\'</span><span>;</span>\n\n<span>// Tell React Cache how to fetch your data</span>\n<span>const</span> TodoResource <span>=</span> <span>unstable_createResource</span><span>(</span>fetchTodo<span>)</span><span>;</span>\n\n<span>function</span> <span>Todo</span><span>(</span>props<span>)</span> <span>{</span>\n  <span>// Suspends until the data is in the cache</span>\n  <span>const</span> todo <span>=</span> TodoResource<span>.</span><span>read</span><span>(</span>props<span>.</span>id<span>)</span><span>;</span>\n  <span>return</span> <span><span><span>&lt;</span>li</span><span>&gt;</span></span><span>{</span>todo<span>.</span>title<span>}</span><span><span><span>&lt;/</span>li</span><span>&gt;</span></span><span>;</span>\n<span>}</span>\n\n<span>function</span> <span>App</span><span>(</span><span>)</span> <span>{</span>\n  <span>return</span> <span>(</span>\n    <span>// Same Suspense component you already use for code splitting</span>\n    <span>// would be able to handle data fetching too.</span>\n    <span><span><span>&lt;</span>React.Suspense</span> <span>fallback</span><span><span>=</span><span>{</span><span><span><span>&lt;</span>Spinner</span> <span>/&gt;</span></span><span>}</span></span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>ul</span><span>&gt;</span></span><span>\n        </span><span>{</span><span>/* Siblings fetch in parallel */</span><span>}</span><span>\n        </span><span><span><span>&lt;</span>Todo</span> <span>id</span><span><span>=</span><span>\"</span>1<span>\"</span></span> <span>/&gt;</span></span><span>\n        </span><span><span><span>&lt;</span>Todo</span> <span>id</span><span><span>=</span><span>\"</span>2<span>\"</span></span> <span>/&gt;</span></span><span>\n      </span><span><span><span>&lt;/</span>ul</span><span>&gt;</span></span><span>\n    </span><span><span><span>&lt;/</span>React.Suspense</span><span>&gt;</span></span>\n  <span>)</span><span>;</span>\n<span>}</span>\n\n<span>// Other libraries like Apollo and Relay can also</span>\n<span>// provide Suspense integrations with similar APIs.</span></code></pre></div>\n<p>There is no official documentation for how to fetch data with Suspense yet, but you can find some early information in <a href=\"https://youtu.be/ByBPyMBTzM0?t=1312\" rel=\"noopener noreferrer\">this talk</a> and <a href=\"https://github.com/facebook/react/blob/master/packages/react-devtools/CHANGELOG.md#suspense-toggle\" rel=\"noopener noreferrer\">this small demo</a>. We‚Äôll write documentation for React Cache (and how to write your own Suspense-compatible library) closer to this React release, but if you‚Äôre curious, you can find its very early source code <a href=\"https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js\" rel=\"noopener noreferrer\">here</a>.</p>\n<p>The low-level Suspense mechanism (suspending rendering and showing a fallback) is expected to be stable even in React 16.6. We‚Äôve used it for code splitting in production for months. However, the higher-level APIs for data fetching are very unstable. React Cache is rapidly changing, and will change at least a few more times. There are some low-level APIs that are <a href=\"https://github.com/reactjs/rfcs/pull/89\" rel=\"noopener noreferrer\">missing</a> for a good higher-level API to be possible. We don‚Äôt recommend using React Cache anywhere except very early experiments. Note that React Cache itself isn‚Äôt strictly tied to React releases, but the current alphas lack basic features as cache invalidation, and you‚Äôll run into a wall very soon. We expect to have something usable with this React release.</p>\n<p>Eventually we‚Äôd like most data fetching to happen through Suspense but it will take a long time until all integrations are ready. In practice we expect it to be adopted very incrementally, and often through layers like Apollo or Relay rather than directly. Missing higher level APIs aren‚Äôt the only obstacle ‚Äî there are also some important UI patterns we don‚Äôt support yet such as <a href=\"https://github.com/facebook/react/issues/14248\" rel=\"noopener noreferrer\">showing progress indicator outside of the loading view hierarchy</a>. As always, we will communicate our progress in the release notes on this blog.</p>\n<p><strong>Status in React DOM and React Native:</strong> Technically, a compatible cache would already work with <code>&lt;React.Suspense&gt;</code> in React 16.6. However, we don‚Äôt expect to have a good cache implementation until this React minor release. If you‚Äôre feeling adventurous, you can try to write your own cache by looking at the React Cache alphas. However, note that the mental model is sufficiently different that there‚Äôs a high risk of misunderstanding it until the docs are ready.</p>\n<p><strong>Status in React DOM Server:</strong> Suspense is not available in the server renderer yet. As we mentioned earlier, we‚Äôve started work on a new asynchronous server renderer that will support Suspense, but it‚Äôs a large project and will take a good chunk of 2019 to complete.</p>\n<p><strong>Recommendation:</strong> Wait for this minor React release in order to use Suspense for data fetching. Don‚Äôt try to use Suspense features in 16.6 for it; it‚Äôs not supported. However, your existing <code>&lt;Suspense&gt;</code> components for code splitting will be able to show loading states for data too when Suspense for Data Fetching becomes officially supported.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#other-projects\" rel=\"noopener noreferrer\"></a>Other Projects </h2>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#modernizing-react-dom\" rel=\"noopener noreferrer\"></a>Modernizing React DOM </h3>\n<p>We started an investigation into <a href=\"https://github.com/facebook/react/issues/13525\" rel=\"noopener noreferrer\">simplifying and modernizing</a> ReactDOM, with a goal of reduced bundle size and aligning closer with the browser behavior. It is still early to say which specific bullet points will ‚Äúmake it‚Äù because the project is in an exploratory phase. We will communicate our progress on that issue.</p>\n<h3><a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#suspense-for-server-rendering\" rel=\"noopener noreferrer\"></a>Suspense for Server Rendering </h3>\n<p>We started designing a new server renderer that supports Suspense (including waiting for asynchronous data on the server without double rendering) and progressively loading and hydrating page content in chunks for best user experience. You can watch an overview of its early prototype in <a href=\"https://www.youtube.com/watch?v=z-6JC0_cOns\" rel=\"noopener noreferrer\">this talk</a>. The new server renderer is going to be our major focus in 2019, but it‚Äôs too early to say anything about its release schedule. Its development, as always, <a href=\"https://github.com/facebook/react/pulls?utf8=%E2%9C%93&amp;q=is%3Apr+is%3Aopen+fizz\" rel=\"noopener noreferrer\">will happen on GitHub</a>.</p>\n<hr>\n<p>And that‚Äôs about it! As you can see, there‚Äôs a lot here to keep us busy but we expect much progress in the coming months.</p>\n<p>We hope this post gives you an idea of what we‚Äôre working on, what you can use today, and what you can expect to use in the future. While there‚Äôs a lot of discussion about new features on social media platforms, you won‚Äôt miss anything important if you read this blog.</p>\n<p>We‚Äôre always open to feedback, and love to hear from you in the <a href=\"https://github.com/reactjs/rfcs\" rel=\"noopener noreferrer\">RFC repository</a>, <a href=\"https://github.com/facebook/react/issues\" rel=\"noopener noreferrer\">the issue tracker</a>, and <a href=\"https://mobile.twitter.com/reactjs\" rel=\"noopener noreferrer\">on Twitter</a>.</p>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2018/12/19/react-v-16-7.html",
        link: "https://reactjs.org/blog/2018/12/19/react-v-16-7.html",
        title: "React v16.7: No, This Is Not the One With Hooks",
        date: 2018-12-19T00:00:00Z,
        summary: Some(
            "Our latest release includes an important performance bugfix for React.lazy. Although there are no API changes, we‚Äôre releasing it as a minor instead of a patch.\nWhy Is This Bugfix a Minor Instead of a Patch? \nReact follows semantic versioning. Typically, this means that we use patch versions for bugfixes, and minors for new (non-breaking) features. However, we reserve the option to release minor versions even if they do not include new features. The motivation is to reserve patches for changes that have a very low chance of breaking. Patches are the most important type of release because they sometimes contain critical bugfixes. That means patch releases have a higher bar for reliability. It‚Äôs unacceptable for a patch to introduce additional bugs, because if people come to distrust patches, it compromises our ability to fix critical bugs when they arise ‚Äî for example, to fix a security vulnerability.\nWe never intend to ship bugs. React has a hard-earned reputation for stability, and we intend to keep it that way. We thoroughly test every version of React before releasing. This includes unit tests, generative (fuzzy) tests, integration tests, and internal dogfooding across tens of thousands of components. However, sometimes we make mistakes. That‚Äôs why, going forward, our policy will be that if a release contains non-trivial changes, we will bump the minor version, even if the external behavior is the same. We‚Äôll also bump the minor when changing unstable_-prefixed APIs.\nCan I Use Hooks Yet? \nNot yet, but soon!\nAt React Conf, we said that 16.7 would be the first release to include Hooks. This was a mistake. We shouldn‚Äôt have attached a specific version number to an unreleased feature. We‚Äôll avoid this in the future.\nAlthough 16.7 does not include Hooks, please do not infer anything about the timeline of the Hooks launch. Our plans for Hooks are unchanged:\n\nThe Hooks proposal was accepted (with minor planned changes in response to feedback).\nThe implementation was merged into the React repo (behind a feature flag).\nWe‚Äôre currently in the testing phase, and you can expect a public release within a few months.\n\nWe‚Äôve heard from many people who want to start using Hooks in their apps. We also can‚Äôt wait to ship them! But because Hooks changes how we write React components, we are taking extra time to get the details right. We appreciate your patience as we prepare this exciting new feature for widespread, ahem, use.\nLearn more about our roadmap in our previous post.\nInstallation \nReact v16.7.0 is available on the npm registry.\nTo install React 16 with Yarn, run:\nyarn add react@^16.7.0 react-dom@^16.7.0\nTo install React 16 with npm, run:\nnpm install --save react@^16.7.0 react-dom@^16.7.0\nWe also provide UMD builds of React via a CDN:\n&lt;script crossorigin src=\"https://unpkg.com/react@16/umd/react.production.min.js\"&gt;&lt;/script&gt;\n&lt;script crossorigin src=\"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js\"&gt;&lt;/script&gt;\nRefer to the documentation for detailed installation instructions.\nChangelog \nReact DOM \n\nFix performance of React.lazy for large numbers of lazily-loaded components. (@acdlite in #14429)\nClear fields on unmount to avoid memory leaks. (@trueadm in #14276)\nFix bug with SSR and context when mixing react-dom/server@16.6 and react@&lt;16.6. (@gaearon in #14291)\nFix a performance regression in profiling mode. (@bvaughn in #14383)\n\nScheduler (Experimental) \n\nPost to MessageChannel instead of window. (@acdlite in #14234)\nReduce serialization overhead. (@developit in #14249)\nFix fallback to setTimeout in testing environments. (@bvaughn in #14358)\nAdd methods for debugging. (@mrkev in #14053)\n",
        ),
        content: Some(
            "<p>Our latest release includes an important performance bugfix for <code>React.lazy</code>. Although there are no API changes, we‚Äôre releasing it as a minor instead of a patch.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#why-is-this-bugfix-a-minor-instead-of-a-patch\" rel=\"noopener noreferrer\"></a>Why Is This Bugfix a Minor Instead of a Patch? </h2>\n<p>React follows <a href=\"https://reactjs.org/docs/faq-versioning.html\" rel=\"noopener noreferrer\">semantic versioning</a>. Typically, this means that we use patch versions for bugfixes, and minors for new (non-breaking) features. However, we reserve the option to release minor versions even if they do not include new features. The motivation is to reserve patches for changes that have a very low chance of breaking. Patches are the most important type of release because they sometimes contain critical bugfixes. That means patch releases have a higher bar for reliability. It‚Äôs unacceptable for a patch to introduce additional bugs, because if people come to distrust patches, it compromises our ability to fix critical bugs when they arise ‚Äî for example, to fix a security vulnerability.</p>\n<p>We never intend to ship bugs. React has a hard-earned reputation for stability, and we intend to keep it that way. We thoroughly test every version of React before releasing. This includes unit tests, generative (fuzzy) tests, integration tests, and internal dogfooding across tens of thousands of components. However, sometimes we make mistakes. That‚Äôs why, going forward, our policy will be that if a release contains non-trivial changes, we will bump the minor version, even if the external behavior is the same. We‚Äôll also bump the minor when changing <code>unstable_</code>-prefixed APIs.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#can-i-use-hooks-yet\" rel=\"noopener noreferrer\"></a>Can I Use Hooks Yet? </h2>\n<p>Not yet, but soon!</p>\n<p>At React Conf, we said that 16.7 would be the first release to include Hooks. This was a mistake. We shouldn‚Äôt have attached a specific version number to an unreleased feature. We‚Äôll avoid this in the future.</p>\n<p>Although 16.7 does not include Hooks, please do not infer anything about the timeline of the Hooks launch. Our plans for Hooks are unchanged:</p>\n<ul>\n<li>The <a href=\"https://github.com/reactjs/rfcs/pull/68\" rel=\"noopener noreferrer\">Hooks proposal</a> was accepted (<a href=\"https://github.com/reactjs/rfcs/pull/68#issuecomment-439314884\" rel=\"noopener noreferrer\">with minor planned changes in response to feedback</a>).</li>\n<li>The <a href=\"https://github.com/facebook/react/commit/7bee9fbdd49aa5b9365a94b0ddf6db04bc1bf51c\" rel=\"noopener noreferrer\">implementation</a> was merged into the React repo (behind a feature flag).</li>\n<li>We‚Äôre currently in the testing phase, and you can expect a public release within a few months.</li>\n</ul>\n<p>We‚Äôve heard from many people who want to start using Hooks in their apps. We also can‚Äôt wait to ship them! But because Hooks changes how we write React components, we are taking extra time to get the details right. We appreciate your patience as we prepare this exciting new feature for widespread, ahem, <em>use</em>.</p>\n<p>Learn more about <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html\" rel=\"noopener noreferrer\">our roadmap</a> in our previous post.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#installation\" rel=\"noopener noreferrer\"></a>Installation </h2>\n<p>React v16.7.0 is available on the npm registry.</p>\n<p>To install React 16 with Yarn, run:</p>\n<div><pre><code>yarn add react@^16.7.0 react-dom@^16.7.0</code></pre></div>\n<p>To install React 16 with npm, run:</p>\n<div><pre><code><span>npm</span> <span>install</span> --save react@^16.7.0 react-dom@^16.7.0</code></pre></div>\n<p>We also provide UMD builds of React via a CDN:</p>\n<div><pre><code><span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react@16/umd/react.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span>\n<span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react-dom@16/umd/react-dom.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span></code></pre></div>\n<p>Refer to the documentation for <a href=\"https://reactjs.org/docs/installation.html\" rel=\"noopener noreferrer\">detailed installation instructions</a>.</p>\n<h2><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#changelog\" rel=\"noopener noreferrer\"></a>Changelog </h2>\n<h3><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#react-dom\" rel=\"noopener noreferrer\"></a>React DOM </h3>\n<ul>\n<li>Fix performance of <code>React.lazy</code> for large numbers of lazily-loaded components. (<a href=\"http://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14429\" rel=\"noopener noreferrer\">#14429</a>)</li>\n<li>Clear fields on unmount to avoid memory leaks. (<a href=\"http://github.com/trueadm\" rel=\"noopener noreferrer\">@trueadm</a> in <a href=\"https://github.com/facebook/react/pull/14276\" rel=\"noopener noreferrer\">#14276</a>)</li>\n<li>Fix bug with SSR and context when mixing <code>react-dom/server@16.6</code> and <code>react@&lt;16.6</code>. (<a href=\"http://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/14291\" rel=\"noopener noreferrer\">#14291</a>)</li>\n<li>Fix a performance regression in profiling mode. (<a href=\"http://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/14383\" rel=\"noopener noreferrer\">#14383</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2018/12/19/react-v-16-7.html#scheduler-experimental\" rel=\"noopener noreferrer\"></a>Scheduler (Experimental) </h3>\n<ul>\n<li>Post to MessageChannel instead of window. (<a href=\"http://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14234\" rel=\"noopener noreferrer\">#14234</a>)</li>\n<li>Reduce serialization overhead. (<a href=\"http://github.com/developit\" rel=\"noopener noreferrer\">@developit</a> in <a href=\"https://github.com/facebook/react/pull/14249\" rel=\"noopener noreferrer\">#14249</a>)</li>\n<li>Fix fallback to <code>setTimeout</code> in testing environments. (<a href=\"http://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/14358\" rel=\"noopener noreferrer\">#14358</a>)</li>\n<li>Add methods for debugging. (<a href=\"http://github.com/mrkev\" rel=\"noopener noreferrer\">@mrkev</a> in <a href=\"https://github.com/facebook/react/pull/14053\" rel=\"noopener noreferrer\">#14053</a>)</li>\n</ul>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/02/06/react-v16.8.0.html",
        link: "https://reactjs.org/blog/2019/02/06/react-v16.8.0.html",
        title: "React v16.8: The One With Hooks",
        date: 2019-02-06T00:00:00Z,
        summary: Some(
            "With React 16.8, React Hooks are available in a stable release!\nWhat Are Hooks? \nHooks let you use state and other React features without writing a class. You can also build your own Hooks to share reusable stateful logic between components.\nIf you‚Äôve never heard of Hooks before, you might find these resources interesting:\n\nIntroducing Hooks explains why we‚Äôre adding Hooks to React.\nHooks at a Glance is a fast-paced overview of the built-in Hooks.\nBuilding Your Own Hooks demonstrates code reuse with custom Hooks.\nMaking Sense of React Hooks explores the new possibilities unlocked by Hooks.\nuseHooks.com showcases community-maintained Hooks recipes and demos.\n\nYou don‚Äôt have to learn Hooks right now. Hooks have no breaking changes, and we have no plans to remove classes from React. The Hooks FAQ describes the gradual adoption strategy.\nNo Big Rewrites \nWe don‚Äôt recommend rewriting your existing applications to use Hooks overnight. Instead, try using Hooks in some of the new components, and let us know what you think. Code using Hooks will work side by side with existing code using classes.\nCan I Use Hooks Today? \nYes! Starting with 16.8.0, React includes a stable implementation of React Hooks for:\n\nReact DOM\nReact DOM Server\nReact Test Renderer\nReact Shallow Renderer\n\nNote that to enable Hooks, all React packages need to be 16.8.0 or higher. Hooks won‚Äôt work if you forget to update, for example, React DOM.\nReact Native will support Hooks in the 0.59 release.\nTooling Support \nReact Hooks are now supported by React DevTools. They are also supported in the latest Flow and TypeScript definitions for React. We strongly recommend enabling a new lint rule called eslint-plugin-react-hooks to enforce best practices with Hooks. It will soon be included into Create React App by default.\nWhat‚Äôs Next \nWe described our plan for the next months in the recently published React Roadmap.\nNote that React Hooks don‚Äôt cover all use cases for classes yet but they‚Äôre very close. Currently, only getSnapshotBeforeUpdate() and componentDidCatch() methods don‚Äôt have equivalent Hooks APIs, and these lifecycles are relatively uncommon. If you want, you should be able to use Hooks in most of the new code you‚Äôre writing.\nEven while Hooks were in alpha, the React community created many interesting examples and recipes using Hooks for animations, forms, subscriptions, integrating with other libraries, and so on. We‚Äôre excited about Hooks because they make code reuse easier, helping you write your components in a simpler way and make great user experiences. We can‚Äôt wait to see what you‚Äôll create next!\nTesting Hooks \nWe have added a new API called ReactTestUtils.act() in this release. It ensures that the behavior in your tests matches what happens in the browser more closely. We recommend to wrap any code rendering and triggering updates to your components into act() calls. Testing libraries can also wrap their APIs with it (for example, react-testing-library‚Äôs render and fireEvent utilities do this).\nFor example, the counter example from this page can be tested like this:\nimport React from \'react\';\nimport ReactDOM from \'react-dom\';\nimport { act } from \'react-dom/test-utils\';\nimport Counter from \'./Counter\';\n\nlet container;\n\nbeforeEach(() =&gt; {\n  container = document.createElement(\'div\');\n  document.body.appendChild(container);\n});\n\nafterEach(() =&gt; {\n  document.body.removeChild(container);\n  container = null;\n});\n\nit(\'can render and update a counter\', () =&gt; {\n  // Test first render and effect\n  act(() =&gt; {\n    ReactDOM.render(&lt;Counter /&gt;, container);\n  });\n  const button = container.querySelector(\'button\');\n  const label = container.querySelector(\'p\');\n  expect(label.textContent).toBe(\'You clicked 0 times\');\n  expect(document.title).toBe(\'You clicked 0 times\');\n\n  // Test second render and effect\n  act(() =&gt; {\n    button.dispatchEvent(new MouseEvent(\'click\', {bubbles: true}));\n  });\n  expect(label.textContent).toBe(\'You clicked 1 times\');\n  expect(document.title).toBe(\'You clicked 1 times\');\n});\nThe calls to act() will also flush the effects inside of them.\nIf you need to test a custom Hook, you can do so by creating a component in your test, and using your Hook from it. Then you can test the component you wrote.\nTo reduce the boilerplate, we recommend using react-testing-library which is designed to encourage writing tests that use your components as the end users do.\nThanks \nWe‚Äôd like to thank everybody who commented on the Hooks RFC for sharing their feedback. We‚Äôve read all of your comments and made some adjustments to the final API based on them.\nInstallation \nReact \nReact v16.8.0 is available on the npm registry.\nTo install React 16 with Yarn, run:\nyarn add react@^16.8.0 react-dom@^16.8.0\nTo install React 16 with npm, run:\nnpm install --save react@^16.8.0 react-dom@^16.8.0\nWe also provide UMD builds of React via a CDN:\n&lt;script crossorigin src=\"https://unpkg.com/react@16/umd/react.production.min.js\"&gt;&lt;/script&gt;\n&lt;script crossorigin src=\"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js\"&gt;&lt;/script&gt;\nRefer to the documentation for detailed installation instructions.\nESLint Plugin for React Hooks \n\nNote\nAs mentioned above, we strongly recommend using the eslint-plugin-react-hooks lint rule.\nIf you‚Äôre using Create React App, instead of manually configuring ESLint you can wait for the next version of react-scripts which will come out shortly and will include this rule.\n\nAssuming you already have ESLint installed, run:\n# npm\nnpm install eslint-plugin-react-hooks --save-dev\n\n# yarn\nyarn add eslint-plugin-react-hooks --dev\nThen add it to your ESLint configuration:\n{\n  \"plugins\": [\n    // ...\n    \"react-hooks\"\n  ],\n  \"rules\": {\n    // ...\n    \"react-hooks/rules-of-hooks\": \"error\"\n  }\n}\nChangelog \nReact \n\nAdd Hooks ‚Äî a way to use state and other React features without writing a class. (@acdlite et al. in #13968)\nImprove the useReducer Hook lazy initialization API. (@acdlite in #14723)\n\nReact DOM \n\nBail out of rendering on identical values for useState and useReducer Hooks. (@acdlite in #14569)\nDon‚Äôt compare the first argument passed to useEffect/useMemo/useCallback Hooks. (@acdlite in #14594)\nUse Object.is algorithm for comparing useState and useReducer values. (@Jessidhia in #14752)\nSupport synchronous thenables passed to React.lazy(). (@gaearon in #14626)\nRender components with Hooks twice in Strict Mode (DEV-only) to match class behavior. (@gaearon in #14654)\nWarn about mismatching Hook order in development. (@threepointone in #14585 and @acdlite in #14591)\nEffect clean-up functions must return either undefined or a function. All other values, including null, are not allowed. @acdlite in #14119\n\nReact Test Renderer \n\nSupport Hooks in the shallow renderer. (@trueadm in #14567)\nFix wrong state in shouldComponentUpdate in the presence of getDerivedStateFromProps for Shallow Renderer. (@chenesan in #14613)\nAdd ReactTestRenderer.act() and ReactTestUtils.act() for batching updates so that tests more closely match real behavior. (@threepointone in #14744)\n\nESLint Plugin: React Hooks \n\nInitial release. (@calebmer in #13968)\nFix reporting after encountering a loop. (@calebmer and @Yurickh in #14661)\nDon‚Äôt consider throwing to be a rule violation. (@sophiebits in #14040)\n\nHooks Changelog Since Alpha Versions \nThe above changelog contains all notable changes since our last stable release (16.7.0). As with all our minor releases, none of the changes break backwards compatibility.\nIf you‚Äôre currently using Hooks from an alpha build of React, note that this release does contain some small breaking changes to Hooks. We don‚Äôt recommend depending on alphas in production code. We publish them so we can make changes in response to community feedback before the API is stable.\nHere are all breaking changes to Hooks that have been made since the first alpha release:\n\nRemove useMutationEffect. (@sophiebits in #14336)\nRename useImperativeMethods to useImperativeHandle. (@threepointone in #14565)\nBail out of rendering on identical values for useState and useReducer Hooks. (@acdlite in #14569)\nDon‚Äôt compare the first argument passed to useEffect/useMemo/useCallback Hooks. (@acdlite in #14594)\nUse Object.is algorithm for comparing useState and useReducer values. (@Jessidhia in #14752)\nRender components with Hooks twice in Strict Mode (DEV-only). (@gaearon in #14654)\nImprove the useReducer Hook lazy initialization API. (@acdlite in #14723)\n",
        ),
        content: Some(
            "<p>With React 16.8, <a href=\"https://reactjs.org/docs/hooks-intro.html\" rel=\"noopener noreferrer\">React Hooks</a> are available in a stable release!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#what-are-hooks\" rel=\"noopener noreferrer\"></a>What Are Hooks? </h2>\n<p>Hooks let you use state and other React features without writing a class. You can also <strong>build your own Hooks</strong> to share reusable stateful logic between components.</p>\n<p>If you‚Äôve never heard of Hooks before, you might find these resources interesting:</p>\n<ul>\n<li><a href=\"https://reactjs.org/docs/hooks-intro.html\" rel=\"noopener noreferrer\">Introducing Hooks</a> explains why we‚Äôre adding Hooks to React.</li>\n<li><a href=\"https://reactjs.org/docs/hooks-overview.html\" rel=\"noopener noreferrer\">Hooks at a Glance</a> is a fast-paced overview of the built-in Hooks.</li>\n<li><a href=\"https://reactjs.org/docs/hooks-custom.html\" rel=\"noopener noreferrer\">Building Your Own Hooks</a> demonstrates code reuse with custom Hooks.</li>\n<li><a href=\"https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889\" rel=\"noopener noreferrer\">Making Sense of React Hooks</a> explores the new possibilities unlocked by Hooks.</li>\n<li><a href=\"https://usehooks.com/\" rel=\"noopener noreferrer\">useHooks.com</a> showcases community-maintained Hooks recipes and demos.</li>\n</ul>\n<p><strong>You don‚Äôt have to learn Hooks right now.</strong> Hooks have no breaking changes, and we have no plans to remove classes from React. The <a href=\"https://reactjs.org/docs/hooks-faq.html\" rel=\"noopener noreferrer\">Hooks FAQ</a> describes the gradual adoption strategy.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#no-big-rewrites\" rel=\"noopener noreferrer\"></a>No Big Rewrites </h2>\n<p>We don‚Äôt recommend rewriting your existing applications to use Hooks overnight. Instead, try using Hooks in some of the new components, and let us know what you think. Code using Hooks will work <a href=\"https://reactjs.org/docs/hooks-intro.html#gradual-adoption-strategy\" rel=\"noopener noreferrer\">side by side</a> with existing code using classes.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#can-i-use-hooks-today\" rel=\"noopener noreferrer\"></a>Can I Use Hooks Today? </h2>\n<p>Yes! Starting with 16.8.0, React includes a stable implementation of React Hooks for:</p>\n<ul>\n<li>React DOM</li>\n<li>React DOM Server</li>\n<li>React Test Renderer</li>\n<li>React Shallow Renderer</li>\n</ul>\n<p>Note that <strong>to enable Hooks, all React packages need to be 16.8.0 or higher</strong>. Hooks won‚Äôt work if you forget to update, for example, React DOM.</p>\n<p><strong>React Native will support Hooks in the <a href=\"https://github.com/react-native-community/react-native-releases/issues/79#issuecomment-457735214\" rel=\"noopener noreferrer\">0.59 release</a>.</strong></p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#tooling-support\" rel=\"noopener noreferrer\"></a>Tooling Support </h2>\n<p>React Hooks are now supported by React DevTools. They are also supported in the latest Flow and TypeScript definitions for React. We strongly recommend enabling a new <a href=\"https://www.npmjs.com/package/eslint-plugin-react-hooks\" rel=\"noopener noreferrer\">lint rule called <code>eslint-plugin-react-hooks</code></a> to enforce best practices with Hooks. It will soon be included into Create React App by default.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#whats-next\" rel=\"noopener noreferrer\"></a>What‚Äôs Next </h2>\n<p>We described our plan for the next months in the recently published <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html\" rel=\"noopener noreferrer\">React Roadmap</a>.</p>\n<p>Note that React Hooks don‚Äôt cover <em>all</em> use cases for classes yet but they‚Äôre <a href=\"https://reactjs.org/docs/hooks-faq.html#do-hooks-cover-all-use-cases-for-classes\" rel=\"noopener noreferrer\">very close</a>. Currently, only <code>getSnapshotBeforeUpdate()</code> and <code>componentDidCatch()</code> methods don‚Äôt have equivalent Hooks APIs, and these lifecycles are relatively uncommon. If you want, you should be able to use Hooks in most of the new code you‚Äôre writing.</p>\n<p>Even while Hooks were in alpha, the React community created many interesting <a href=\"https://codesandbox.io/react-hooks\" rel=\"noopener noreferrer\">examples</a> and <a href=\"https://usehooks.com/\" rel=\"noopener noreferrer\">recipes</a> using Hooks for animations, forms, subscriptions, integrating with other libraries, and so on. We‚Äôre excited about Hooks because they make code reuse easier, helping you write your components in a simpler way and make great user experiences. We can‚Äôt wait to see what you‚Äôll create next!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#testing-hooks\" rel=\"noopener noreferrer\"></a>Testing Hooks </h2>\n<p>We have added a new API called <code>ReactTestUtils.act()</code> in this release. It ensures that the behavior in your tests matches what happens in the browser more closely. We recommend to wrap any code rendering and triggering updates to your components into <code>act()</code> calls. Testing libraries can also wrap their APIs with it (for example, <a href=\"https://testing-library.com/react\" rel=\"noopener noreferrer\"><code>react-testing-library</code></a>‚Äôs <code>render</code> and <code>fireEvent</code> utilities do this).</p>\n<p>For example, the counter example from <a href=\"https://reactjs.org/docs/hooks-effect.html\" rel=\"noopener noreferrer\">this page</a> can be tested like this:</p>\n<div><pre><code><span>import</span> React <span>from</span> <span>\'react\'</span><span>;</span>\n<span>import</span> ReactDOM <span>from</span> <span>\'react-dom\'</span><span>;</span>\n<span><span>import</span> <span>{</span> act <span>}</span> <span>from</span> <span>\'react-dom/test-utils\'</span><span>;</span>\n</span><span>import</span> Counter <span>from</span> <span>\'./Counter\'</span><span>;</span>\n\n<span>let</span> container<span>;</span>\n\n<span>beforeEach</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n  container <span>=</span> document<span>.</span><span>createElement</span><span>(</span><span>\'div\'</span><span>)</span><span>;</span>\n  document<span>.</span>body<span>.</span><span>appendChild</span><span>(</span>container<span>)</span><span>;</span>\n<span>}</span><span>)</span><span>;</span>\n\n<span>afterEach</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n  document<span>.</span>body<span>.</span><span>removeChild</span><span>(</span>container<span>)</span><span>;</span>\n  container <span>=</span> <span>null</span><span>;</span>\n<span>}</span><span>)</span><span>;</span>\n\n<span>it</span><span>(</span><span>\'can render and update a counter\'</span><span>,</span> <span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n  <span>// Test first render and effect</span>\n<span>  <span>act</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n</span><span>    ReactDOM<span>.</span><span>render</span><span>(</span><span><span><span>&lt;</span>Counter</span> <span>/&gt;</span></span><span>,</span> container<span>)</span><span>;</span>\n</span><span>  <span>}</span><span>)</span><span>;</span>\n</span>  <span>const</span> button <span>=</span> container<span>.</span><span>querySelector</span><span>(</span><span>\'button\'</span><span>)</span><span>;</span>\n  <span>const</span> label <span>=</span> container<span>.</span><span>querySelector</span><span>(</span><span>\'p\'</span><span>)</span><span>;</span>\n  <span>expect</span><span>(</span>label<span>.</span>textContent<span>)</span><span>.</span><span>toBe</span><span>(</span><span>\'You clicked 0 times\'</span><span>)</span><span>;</span>\n  <span>expect</span><span>(</span>document<span>.</span>title<span>)</span><span>.</span><span>toBe</span><span>(</span><span>\'You clicked 0 times\'</span><span>)</span><span>;</span>\n\n  <span>// Test second render and effect</span>\n<span>  <span>act</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n</span><span>    button<span>.</span><span>dispatchEvent</span><span>(</span><span>new</span> <span>MouseEvent</span><span>(</span><span>\'click\'</span><span>,</span> <span>{</span>bubbles<span>:</span> <span>true</span><span>}</span><span>)</span><span>)</span><span>;</span>\n</span><span>  <span>}</span><span>)</span><span>;</span>\n</span>  <span>expect</span><span>(</span>label<span>.</span>textContent<span>)</span><span>.</span><span>toBe</span><span>(</span><span>\'You clicked 1 times\'</span><span>)</span><span>;</span>\n  <span>expect</span><span>(</span>document<span>.</span>title<span>)</span><span>.</span><span>toBe</span><span>(</span><span>\'You clicked 1 times\'</span><span>)</span><span>;</span>\n<span>}</span><span>)</span><span>;</span></code></pre></div>\n<p>The calls to <code>act()</code> will also flush the effects inside of them.</p>\n<p>If you need to test a custom Hook, you can do so by creating a component in your test, and using your Hook from it. Then you can test the component you wrote.</p>\n<p>To reduce the boilerplate, we recommend using <a href=\"https://testing-library.com/react\" rel=\"noopener noreferrer\"><code>react-testing-library</code></a> which is designed to encourage writing tests that use your components as the end users do.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#thanks\" rel=\"noopener noreferrer\"></a>Thanks </h2>\n<p>We‚Äôd like to thank everybody who commented on the <a href=\"https://github.com/reactjs/rfcs/pull/68\" rel=\"noopener noreferrer\">Hooks RFC</a> for sharing their feedback. We‚Äôve read all of your comments and made some adjustments to the final API based on them.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#installation\" rel=\"noopener noreferrer\"></a>Installation </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#react\" rel=\"noopener noreferrer\"></a>React </h3>\n<p>React v16.8.0 is available on the npm registry.</p>\n<p>To install React 16 with Yarn, run:</p>\n<div><pre><code>yarn add react@^16.8.0 react-dom@^16.8.0</code></pre></div>\n<p>To install React 16 with npm, run:</p>\n<div><pre><code><span>npm</span> <span>install</span> --save react@^16.8.0 react-dom@^16.8.0</code></pre></div>\n<p>We also provide UMD builds of React via a CDN:</p>\n<div><pre><code><span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react@16/umd/react.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span>\n<span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react-dom@16/umd/react-dom.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span></code></pre></div>\n<p>Refer to the documentation for <a href=\"https://reactjs.org/docs/installation.html\" rel=\"noopener noreferrer\">detailed installation instructions</a>.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#eslint-plugin-for-react-hooks\" rel=\"noopener noreferrer\"></a>ESLint Plugin for React Hooks </h3>\n<blockquote>\n<p>Note</p>\n<p>As mentioned above, we strongly recommend using the <code>eslint-plugin-react-hooks</code> lint rule.</p>\n<p>If you‚Äôre using Create React App, instead of manually configuring ESLint you can wait for the next version of <code>react-scripts</code> which will come out shortly and will include this rule.</p>\n</blockquote>\n<p>Assuming you already have ESLint installed, run:</p>\n<div><pre><code># npm\nnpm install eslint-plugin-react-hooks --save-dev\n\n# yarn\nyarn add eslint-plugin-react-hooks --dev</code></pre></div>\n<p>Then add it to your ESLint configuration:</p>\n<div><pre><code><span>{</span>\n  <span>\"plugins\"</span><span>:</span> <span>[</span>\n    <span>// ...</span>\n    <span>\"react-hooks\"</span>\n  <span>]</span><span>,</span>\n  <span>\"rules\"</span><span>:</span> <span>{</span>\n    <span>// ...</span>\n    <span>\"react-hooks/rules-of-hooks\"</span><span>:</span> <span>\"error\"</span>\n  <span>}</span>\n<span>}</span></code></pre></div>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#changelog\" rel=\"noopener noreferrer\"></a>Changelog </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#react-1\" rel=\"noopener noreferrer\"></a>React </h3>\n<ul>\n<li>Add <a href=\"https://reactjs.org/docs/hooks-intro.html\" rel=\"noopener noreferrer\">Hooks</a> ‚Äî a way to use state and other React features without writing a class. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> et al. in <a href=\"https://github.com/facebook/react/pull/13968\" rel=\"noopener noreferrer\">#13968</a>)</li>\n<li>Improve the <code>useReducer</code> Hook lazy initialization API. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14723\" rel=\"noopener noreferrer\">#14723</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#react-dom\" rel=\"noopener noreferrer\"></a>React DOM </h3>\n<ul>\n<li>Bail out of rendering on identical values for <code>useState</code> and <code>useReducer</code> Hooks. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14569\" rel=\"noopener noreferrer\">#14569</a>)</li>\n<li>Don‚Äôt compare the first argument passed to <code>useEffect</code>/<code>useMemo</code>/<code>useCallback</code> Hooks. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14594\" rel=\"noopener noreferrer\">#14594</a>)</li>\n<li>Use <code>Object.is</code> algorithm for comparing <code>useState</code> and <code>useReducer</code> values. (<a href=\"https://github.com/Jessidhia\" rel=\"noopener noreferrer\">@Jessidhia</a> in <a href=\"https://github.com/facebook/react/pull/14752\" rel=\"noopener noreferrer\">#14752</a>)</li>\n<li>Support synchronous thenables passed to <code>React.lazy()</code>. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/14626\" rel=\"noopener noreferrer\">#14626</a>)</li>\n<li>Render components with Hooks twice in Strict Mode (DEV-only) to match class behavior. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/14654\" rel=\"noopener noreferrer\">#14654</a>)</li>\n<li>Warn about mismatching Hook order in development. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/14585\" rel=\"noopener noreferrer\">#14585</a> and <a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14591\" rel=\"noopener noreferrer\">#14591</a>)</li>\n<li>Effect clean-up functions must return either <code>undefined</code> or a function. All other values, including <code>null</code>, are not allowed. <a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14119\" rel=\"noopener noreferrer\">#14119</a></li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#react-test-renderer\" rel=\"noopener noreferrer\"></a>React Test Renderer </h3>\n<ul>\n<li>Support Hooks in the shallow renderer. (<a href=\"https://github.com/trueadm\" rel=\"noopener noreferrer\">@trueadm</a> in <a href=\"https://github.com/facebook/react/pull/14567\" rel=\"noopener noreferrer\">#14567</a>)</li>\n<li>Fix wrong state in <code>shouldComponentUpdate</code> in the presence of <code>getDerivedStateFromProps</code> for Shallow Renderer. (<a href=\"https://github.com/chenesan\" rel=\"noopener noreferrer\">@chenesan</a> in <a href=\"https://github.com/facebook/react/pull/14613\" rel=\"noopener noreferrer\">#14613</a>)</li>\n<li>Add <code>ReactTestRenderer.act()</code> and <code>ReactTestUtils.act()</code> for batching updates so that tests more closely match real behavior. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/14744\" rel=\"noopener noreferrer\">#14744</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#eslint-plugin-react-hooks\" rel=\"noopener noreferrer\"></a>ESLint Plugin: React Hooks </h3>\n<ul>\n<li>Initial <a href=\"https://www.npmjs.com/package/eslint-plugin-react-hooks\" rel=\"noopener noreferrer\">release</a>. (<a href=\"https://github.com/calebmer\" rel=\"noopener noreferrer\">@calebmer</a> in <a href=\"https://github.com/facebook/react/pull/13968\" rel=\"noopener noreferrer\">#13968</a>)</li>\n<li>Fix reporting after encountering a loop. (<a href=\"https://github.com/calebmer\" rel=\"noopener noreferrer\">@calebmer</a> and <a href=\"https://github.com/Yurickh\" rel=\"noopener noreferrer\">@Yurickh</a> in <a href=\"https://github.com/facebook/react/pull/14661\" rel=\"noopener noreferrer\">#14661</a>)</li>\n<li>Don‚Äôt consider throwing to be a rule violation. (<a href=\"https://github.com/sophiebits\" rel=\"noopener noreferrer\">@sophiebits</a> in <a href=\"https://github.com/facebook/react/pull/14040\" rel=\"noopener noreferrer\">#14040</a>)</li>\n</ul>\n<h2><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html#hooks-changelog-since-alpha-versions\" rel=\"noopener noreferrer\"></a>Hooks Changelog Since Alpha Versions </h2>\n<p>The above changelog contains all notable changes since our last <strong>stable</strong> release (16.7.0). <a href=\"https://reactjs.org/docs/faq-versioning.html\" rel=\"noopener noreferrer\">As with all our minor releases</a>, none of the changes break backwards compatibility.</p>\n<p>If you‚Äôre currently using Hooks from an alpha build of React, note that this release does contain some small breaking changes to Hooks. <strong>We don‚Äôt recommend depending on alphas in production code.</strong> We publish them so we can make changes in response to community feedback before the API is stable.</p>\n<p>Here are all breaking changes to Hooks that have been made since the first alpha release:</p>\n<ul>\n<li>Remove <code>useMutationEffect</code>. (<a href=\"https://github.com/sophiebits\" rel=\"noopener noreferrer\">@sophiebits</a> in <a href=\"https://github.com/facebook/react/pull/14336\" rel=\"noopener noreferrer\">#14336</a>)</li>\n<li>Rename <code>useImperativeMethods</code> to <code>useImperativeHandle</code>. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/14565\" rel=\"noopener noreferrer\">#14565</a>)</li>\n<li>Bail out of rendering on identical values for <code>useState</code> and <code>useReducer</code> Hooks. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14569\" rel=\"noopener noreferrer\">#14569</a>)</li>\n<li>Don‚Äôt compare the first argument passed to <code>useEffect</code>/<code>useMemo</code>/<code>useCallback</code> Hooks. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14594\" rel=\"noopener noreferrer\">#14594</a>)</li>\n<li>Use <code>Object.is</code> algorithm for comparing <code>useState</code> and <code>useReducer</code> values. (<a href=\"https://github.com/Jessidhia\" rel=\"noopener noreferrer\">@Jessidhia</a> in <a href=\"https://github.com/facebook/react/pull/14752\" rel=\"noopener noreferrer\">#14752</a>)</li>\n<li>Render components with Hooks twice in Strict Mode (DEV-only). (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/14654\" rel=\"noopener noreferrer\">#14654</a>)</li>\n<li>Improve the <code>useReducer</code> Hook lazy initialization API. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/14723\" rel=\"noopener noreferrer\">#14723</a>)</li>\n</ul>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html",
        link: "https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html",
        title: "Is React Translated Yet? ¬°S√≠! Sim! „ÅØ„ÅÑÔºÅ",
        date: 2019-02-23T00:00:00Z,
        summary: Some(
            "We‚Äôre excited to announce an ongoing effort to maintain official translations of the React documentation website into different languages. Thanks to the dedicated efforts of React community members from around the world, React is now being translated into over 30 languages! You can find them on the new Languages page.\nIn addition, the following three languages have completed translating most of the React Docs! üéâ\n\nSpanish: es.reactjs.org\nJapanese: ja.reactjs.org\nBrazilian Portuguese: pt-br.reactjs.org\n\nSpecial congratulations to Alejandro √ë√°√±ez Ortiz, Rainer Mart√≠nez Fraga, David Morales, Miguel Alejandro Bolivar Portilla, and all the contributors to the Spanish translation for being the first to completely translate the core pages of the docs!\nWhy Localization Matters \nReact already has many meetups and conferences around the world, but many programmers don‚Äôt use English as their primary language. We‚Äôd love to support local communities who use React by making our documentation available in most popular languages.\nIn the past, React community members have created unofficial translations for Chinese, Arabic, and Korean; by making an official channel for these translated docs we‚Äôre hoping to make them easier to find and help make sure that non-English-speaking users of React aren‚Äôt left behind.\nContributing \nIf you would like to help out on a current translation, check out the Languages page and click on the ‚ÄúContribute‚Äù link for your language.\nCan‚Äôt find your language? If you‚Äôd like to maintain your language‚Äôs translation fork, follow the instructions in the translation repo!\nBackstory \nHi everyone! I‚Äôm Nat! You may know me as the polyhedra lady. For the past few weeks, I‚Äôve been helping the React team coordinate their translation effort. Here‚Äôs how I did it.\nOur original approach for translations was to use a SaaS platform that allows users to submit translations. There was already a pull request to integrate it and my original responsibility was to finish that integration. However, we had concerns about the feasibility of that integration and the current quality of translations on the platform. Our primary concern was ensuring that translations kept up to date with the main repo and didn‚Äôt become ‚Äústale‚Äù.\nDan encouraged me to look for alternate solutions, and we stumbled across how Vue maintained its translations ‚Äî through different forks of the main repo on GitHub. In particular, the Japanese translation used a bot to periodically check for changes in the English repo and submits pull requests whenever there is a change.\nThis approach appealed to us for several reasons:\n\nIt was less code integration to get off the ground.\nIt encouraged active maintainers for each repo to ensure quality.\nContributors already understand GitHub as a platform and are motivated to contribute directly to the React organization.\n\nWe started off with an initial trial period of three languages: Spanish, Japanese, and Simplified Chinese. This allowed us to work out any kinks in our process and make sure future translations are set up for success. I wanted to give the translation teams freedom to choose whatever tools they felt comfortable with. The only requirement is a checklist that outlines the order of importance for translating pages. \nAfter the trial period, we were ready to accept more languages. I created a script to automate the creation of the new language repo, and a site, Is React Translated Yet?, to track progress on the different translations. We started 10 new translations on our first day alone!\nBecause of the automation, the rest of the maintenance went mostly smoothly. We eventually created a Slack channel to make it easier for translators to share information, and I released a guide solidifying the responsibilities of maintainers. Allowing translators to talk with each other was a great boon ‚Äî for example, the Arabic, Persian, and Hebrew translations were able to talk to each other in order to get right-to-left text working!\nThe Bot \nThe most challenging part was getting the bot to sync changes from the English version of the site. Initially we were using the che-tsumi bot created by the Japanese Vue translation team, but we soon decided to build our own bot to suit our needs. In particular, the che-tsumi bot works by cherry picking new commits. This ended up causing a cavalade of new issues that were interconnected, especially when Hooks were released.\nIn the end, we decided that instead of cherry picking each commit, it made more sense to merge all new commits and create a pull request around once a day. Conflicts are merged as-is and listed in the pull request, leaving a checklist for maintainers to fix.\nCreating the sync script was easy enough: it downloads the translated repo, adds the original as a remote, pulls from it, merges the conflicts, and creates a pull request.\nThe problem was finding a place for the bot to run. I‚Äôm a frontend developer for a reason ‚Äî Heroku and its ilk are alien to me and endlessly frustrating. In fact, until this past Tuesday, I was running the script by hand on my local machine!\nThe biggest challenge was space. Each fork of the repo is around 100MB ‚Äî which takes minutes to clone on my local machine. We have 32 forks, and the free tiers or most deployment platforms I checked limited you to 512MB of storage. \nAfter lots of notepad calculations, I found a solution: delete each repo once we‚Äôve finished the script and limit the concurrency of sync scripts that run at once to be within the storage requirements. Luckily, Heroku dynos have a much faster Internet connection and are able to clone even the React repo quickly.\nThere were other smaller issues that I ran into. I tried using the Heroku Scheduler add-on so I didn‚Äôt have to write any actual watch code, but it end up running too inconsistently, and I had an existential meltdown on Twitter when I couldn‚Äôt figure out how to send commits from the Heroku dyno. But in the end, this frontend engineer was able to get the bot working!\nThere are, as always, improvements I want to make to the bot. Right now it doesn‚Äôt check whether there is an outstanding pull request before pushing another one. It‚Äôs still hard to tell the exact change that happened in the original source, and it‚Äôs possible to miss out on a needed translation change. But I trust the maintainers we‚Äôve chosen to work through these issues, and the bot is open source if anyone wants to help me make these improvements!\nThanks \nFinally, I would like to extend my gratitude to the following people and groups:\n\nAll the translation maintainers and contributors who are helping translate React to more than thirty languages.\nThe Vue.js Japan User Group for initiating the idea of having bot-managed translations, and especially Hanatani Takuma for helping us understand their approach and helping maintain the Japanese translation.\nSoichiro Miki for many contributions and thoughtful comments on the overall translation process, as well as for maintaining the Japanese translation.\nEric Nakagawa for managing our previous translation process.\nBrian Vaughn for setting up the languages page and managing all the subdomains.\n\n And finally, thank you to Dan Abramov for giving me this opportunity and being a great mentor along the way.",
        ),
        content: Some(
            "<p>We‚Äôre excited to announce an ongoing effort to maintain official translations of the React documentation website into different languages. Thanks to the dedicated efforts of React community members from around the world, React is now being translated into <em>over 30</em> languages! You can find them on the new <a href=\"https://reactjs.org/languages\" rel=\"noopener noreferrer\">Languages</a> page.</p>\n<p>In addition, the following three languages have completed translating most of the React Docs! üéâ</p>\n<ul>\n<li><strong>Spanish: <a href=\"https://es.reactjs.org/\" rel=\"noopener noreferrer\">es.reactjs.org</a></strong></li>\n<li><strong>Japanese: <a href=\"https://ja.reactjs.org/\" rel=\"noopener noreferrer\">ja.reactjs.org</a></strong></li>\n<li><strong>Brazilian Portuguese: <a href=\"https://pt-br.reactjs.org/\" rel=\"noopener noreferrer\">pt-br.reactjs.org</a></strong></li>\n</ul>\n<p>Special congratulations to <a href=\"https://github.com/alejandronanez\" rel=\"noopener noreferrer\">Alejandro √ë√°√±ez Ortiz</a>, <a href=\"https://github.com/carburo\" rel=\"noopener noreferrer\">Rainer Mart√≠nez Fraga</a>, <a href=\"https://github.com/dmorales\" rel=\"noopener noreferrer\">David Morales</a>, <a href=\"https://github.com/Darking360\" rel=\"noopener noreferrer\">Miguel Alejandro Bolivar Portilla</a>, and all the contributors to the Spanish translation for being the first to <em>completely</em> translate the core pages of the docs!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html#why-localization-matters\" rel=\"noopener noreferrer\"></a>Why Localization Matters </h2>\n<p>React already has many meetups and conferences around the world, but many programmers don‚Äôt use English as their primary language. We‚Äôd love to support local communities who use React by making our documentation available in most popular languages.</p>\n<p>In the past, React community members have created unofficial translations for <a href=\"https://github.com/discountry/react\" rel=\"noopener noreferrer\">Chinese</a>, <a href=\"https://wiki.hsoub.com/React\" rel=\"noopener noreferrer\">Arabic</a>, and <a href=\"https://github.com/reactjs/ko.reactjs.org/issues/4\" rel=\"noopener noreferrer\">Korean</a>; by making an official channel for these translated docs we‚Äôre hoping to make them easier to find and help make sure that non-English-speaking users of React aren‚Äôt left behind.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html#contributing\" rel=\"noopener noreferrer\"></a>Contributing </h2>\n<p>If you would like to help out on a current translation, check out the <a href=\"https://reactjs.org/languages\" rel=\"noopener noreferrer\">Languages</a> page and click on the ‚ÄúContribute‚Äù link for your language.</p>\n<p>Can‚Äôt find your language? If you‚Äôd like to maintain your language‚Äôs translation fork, follow the instructions in the <a href=\"https://github.com/reactjs/reactjs.org-translation#starting-a-new-translation\" rel=\"noopener noreferrer\">translation repo</a>!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html#backstory\" rel=\"noopener noreferrer\"></a>Backstory </h2>\n<p>Hi everyone! I‚Äôm <a href=\"https://twitter.com/tesseralis\" rel=\"noopener noreferrer\">Nat</a>! You may know me as the <a href=\"https://www.youtube.com/watch?v=Ew-UzGC8RqQ\" rel=\"noopener noreferrer\">polyhedra lady</a>. For the past few weeks, I‚Äôve been helping the React team coordinate their translation effort. Here‚Äôs how I did it.</p>\n<p>Our original approach for translations was to use a SaaS platform that allows users to submit translations. There was already a <a href=\"https://github.com/reactjs/reactjs.org/pull/873\" rel=\"noopener noreferrer\">pull request</a> to integrate it and my original responsibility was to finish that integration. However, we had concerns about the feasibility of that integration and the current quality of translations on the platform. Our primary concern was ensuring that translations kept up to date with the main repo and didn‚Äôt become ‚Äústale‚Äù.</p>\n<p><a href=\"https://twitter.com/dan_abramov\" rel=\"noopener noreferrer\">Dan</a> encouraged me to look for alternate solutions, and we stumbled across how <a href=\"https://vuejs.org/\" rel=\"noopener noreferrer\">Vue</a> maintained its translations ‚Äî through different forks of the main repo on GitHub. In particular, the <a href=\"https://jp.vuejs.org/\" rel=\"noopener noreferrer\">Japanese translation</a> used a bot to periodically check for changes in the English repo and submits pull requests whenever there is a change.</p>\n<p>This approach appealed to us for several reasons:</p>\n<ul>\n<li>It was less code integration to get off the ground.</li>\n<li>It encouraged active maintainers for each repo to ensure quality.</li>\n<li>Contributors already understand GitHub as a platform and are motivated to contribute directly to the React organization.</li>\n</ul>\n<p>We started off with an initial trial period of three languages: Spanish, Japanese, and Simplified Chinese. This allowed us to work out any kinks in our process and make sure future translations are set up for success. I wanted to give the translation teams freedom to choose whatever tools they felt comfortable with. The only requirement is a <a href=\"https://github.com/reactjs/reactjs.org-translation/blob/master/PROGRESS.template.md\" rel=\"noopener noreferrer\">checklist</a> that outlines the order of importance for translating pages. </p>\n<p>After the trial period, we were ready to accept more languages. I created <a href=\"https://github.com/reactjs/reactjs.org-translation/blob/master/scripts/create.js\" rel=\"noopener noreferrer\">a script</a> to automate the creation of the new language repo, and a site, <a href=\"https://isreacttranslatedyet.com/\" rel=\"noopener noreferrer\">Is React Translated Yet?</a>, to track progress on the different translations. We started <em>10</em> new translations on our first day alone!</p>\n<p>Because of the automation, the rest of the maintenance went mostly smoothly. We eventually created a <a href=\"https://rt-slack-invite.herokuapp.com/\" rel=\"noopener noreferrer\">Slack channel</a> to make it easier for translators to share information, and I released a guide solidifying the <a href=\"https://github.com/reactjs/reactjs.org-translation/blob/master/maintainer-guide.md\" rel=\"noopener noreferrer\">responsibilities of maintainers</a>. Allowing translators to talk with each other was a great boon ‚Äî for example, the Arabic, Persian, and Hebrew translations were able to talk to each other in order to get <a href=\"https://en.wikipedia.org/wiki/Right-to-left\" rel=\"noopener noreferrer\">right-to-left text</a> working!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html#the-bot\" rel=\"noopener noreferrer\"></a>The Bot </h2>\n<p>The most challenging part was getting the bot to sync changes from the English version of the site. Initially we were using the <a href=\"https://github.com/vuejs-jp/che-tsumi\" rel=\"noopener noreferrer\">che-tsumi</a> bot created by the Japanese Vue translation team, but we soon decided to build our own bot to suit our needs. In particular, the che-tsumi bot works by <a href=\"https://git-scm.com/docs/git-cherry-pick\" rel=\"noopener noreferrer\">cherry picking</a> new commits. This ended up causing a cavalade of new issues that were interconnected, especially when <a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html\" rel=\"noopener noreferrer\">Hooks were released</a>.</p>\n<p>In the end, we decided that instead of cherry picking each commit, it made more sense to merge all new commits and create a pull request around once a day. Conflicts are merged as-is and listed in the <a href=\"https://github.com/reactjs/pt-BR.reactjs.org/pull/114\" rel=\"noopener noreferrer\">pull request</a>, leaving a checklist for maintainers to fix.</p>\n<p>Creating the <a href=\"https://github.com/reactjs/reactjs.org-translation/blob/master/scripts/sync.js\" rel=\"noopener noreferrer\">sync script</a> was easy enough: it downloads the translated repo, adds the original as a remote, pulls from it, merges the conflicts, and creates a pull request.</p>\n<p>The problem was finding a place for the bot to run. I‚Äôm a frontend developer for a reason ‚Äî Heroku and its ilk are alien to me and <em>endlessly</em> frustrating. In fact, until this past Tuesday, I was running the script by hand on my local machine!</p>\n<p>The biggest challenge was space. Each fork of the repo is around 100MB ‚Äî which takes minutes to clone on my local machine. We have <em>32</em> forks, and the free tiers or most deployment platforms I checked limited you to 512MB of storage. </p>\n<p>After lots of notepad calculations, I found a solution: delete each repo once we‚Äôve finished the script and limit the concurrency of <code>sync</code> scripts that run at once to be within the storage requirements. Luckily, Heroku dynos have a much faster Internet connection and are able to clone even the React repo quickly.</p>\n<p>There were other smaller issues that I ran into. I tried using the <a href=\"https://elements.heroku.com/addons/scheduler\" rel=\"noopener noreferrer\">Heroku Scheduler</a> add-on so I didn‚Äôt have to write any actual <code>watch</code> code, but it end up running too inconsistently, and I <a href=\"https://twitter.com/tesseralis/status/1097387938088796160\" rel=\"noopener noreferrer\">had an existential meltdown on Twitter</a> when I couldn‚Äôt figure out how to send commits from the Heroku dyno. But in the end, this frontend engineer was able to get the bot working!</p>\n<p>There are, as always, improvements I want to make to the bot. Right now it doesn‚Äôt check whether there is an outstanding pull request before pushing another one. It‚Äôs still hard to tell the exact change that happened in the original source, and it‚Äôs possible to miss out on a needed translation change. But I trust the maintainers we‚Äôve chosen to work through these issues, and the bot is <a href=\"https://github.com/reactjs/reactjs.org-translation\" rel=\"noopener noreferrer\">open source</a> if anyone wants to help me make these improvements!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/02/23/is-react-translated-yet.html#thanks\" rel=\"noopener noreferrer\"></a>Thanks </h2>\n<p>Finally, I would like to extend my gratitude to the following people and groups:</p>\n<ul>\n<li>All the translation maintainers and contributors who are helping translate React to more than thirty languages.</li>\n<li>The <a href=\"https://github.com/vuejs-jp\" rel=\"noopener noreferrer\">Vue.js Japan User Group</a> for initiating the idea of having bot-managed translations, and especially <a href=\"https://github.com/potato4d\" rel=\"noopener noreferrer\">Hanatani Takuma</a> for helping us understand their approach and helping maintain the Japanese translation.</li>\n<li><a href=\"https://github.com/smikitky\" rel=\"noopener noreferrer\">Soichiro Miki</a> for many <a href=\"https://github.com/reactjs/reactjs.org/pull/1636\" rel=\"noopener noreferrer\">contributions</a> and thoughtful comments on the overall translation process, as well as for maintaining the Japanese translation.</li>\n<li><a href=\"https://github.com/ericnakagawa\" rel=\"noopener noreferrer\">Eric Nakagawa</a> for managing our previous translation process.</li>\n<li><a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">Brian Vaughn</a> for setting up the <a href=\"https://reactjs.org/languages\" rel=\"noopener noreferrer\">languages page</a> and managing all the subdomains.</li>\n</ul>\n<p> And finally, thank you to <a href=\"https://twitter.com/dan_abramov\" rel=\"noopener noreferrer\">Dan Abramov</a> for giving me this opportunity and being a great mentor along the way.</p>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/08/08/react-v16.9.0.html",
        link: "https://reactjs.org/blog/2019/08/08/react-v16.9.0.html",
        title: "React v16.9.0 and the Roadmap Update",
        date: 2019-08-08T00:00:00Z,
        summary: Some(
            "Today we are releasing React 16.9. It contains several new features, bugfixes, and new deprecation warnings to help prepare for a future major release. \nNew Deprecations \nRenaming Unsafe Lifecycle Methods \nOver a year ago, we announced that unsafe lifecycle methods are getting renamed:\n\ncomponentWillMount ‚Üí UNSAFE_componentWillMount\ncomponentWillReceiveProps ‚Üí UNSAFE_componentWillReceiveProps\ncomponentWillUpdate ‚Üí UNSAFE_componentWillUpdate\n\nReact 16.9 does not contain breaking changes, and the old names continue to work in this release. But you will now see a warning when using any of the old names:\n\nAs the warning suggests, there are usually better approaches for each of the unsafe methods. However, maybe you don‚Äôt have the time to migrate or test these components. In that case, we recommend running a ‚Äúcodemod‚Äù script that renames them automatically:\ncd your_project\nnpx react-codemod rename-unsafe-lifecycles\n(Note that it says npx, not npm. npx is a utility that comes with Node 6+ by default.)\nRunning this codemod will replace the old names like componentWillMount with the new names like UNSAFE_componentWillMount:\n\nThe new names like UNSAFE_componentWillMount will keep working in both React 16.9 and in React 17.x. However, the new UNSAFE_ prefix will help components with problematic patterns stand out during the code review and debugging sessions. (If you‚Äôd like, you can further discourage their use inside your app with the opt-in Strict Mode.)\n\nNote\nLearn more about our versioning policy and commitment to stability.\n\nDeprecating javascript: URLs \nURLs starting with javascript: are a dangerous attack surface because it‚Äôs easy to accidentally include unsanitized output in a tag like &lt;a href&gt; and create a security hole:\nconst userProfile = {\n  website: \"javascript: alert(\'you got hacked\')\",\n};\n// This will now warn:\n&lt;a href={userProfile.website}&gt;Profile&lt;/a&gt;\nIn React 16.9, this pattern continues to work, but it will log a warning. If you use javascript: URLs for logic, try to use React event handlers instead. (As a last resort, you can circumvent the protection with dangerouslySetInnerHTML, but it is highly discouraged and often leads to security holes.)\nIn a future major release, React will throw an error if it encounters a javascript: URL.\nDeprecating ‚ÄúFactory‚Äù Components \nBefore compiling JavaScript classes with Babel became popular, React had support for a ‚Äúfactory‚Äù component that returns an object with a render method:\nfunction FactoryComponent() {\n  return { render() { return &lt;div /&gt;; } }\n}\nThis pattern is confusing because it looks too much like a function component ‚Äî but it isn‚Äôt one. (A function component would just return the &lt;div /&gt; in the above example.)\nThis pattern was almost never used in the wild, and supporting it causes React to be slightly larger and slower than necessary. So we are deprecating this pattern in 16.9 and logging a warning if it‚Äôs encountered. If you rely on it, adding FactoryComponent.prototype = React.Component.prototype can serve as a workaround. Alternatively, you can convert it to either a class or a function component.\nWe don‚Äôt expect most codebases to be affected by this.\nNew Features \nAsync act() for Testing \nReact 16.8 introduced a new testing utility called act() to help you write tests that better match the browser behavior. For example, multiple state updates inside a single act() get batched. This matches how React already works when handling real browser events, and helps prepare your components for the future in which React will batch updates more often.\nHowever, in 16.8 act() only supported synchronous functions. Sometimes, you might have seen a warning like this in a test but could not easily fix it:\nAn update to SomeComponent inside a test was not wrapped in act(...).\nIn React 16.9, act() also accepts asynchronous functions, and you can await its call:\nawait act(async () =&gt; {\n  // ...\n});\nThis solves the remaining cases where you couldn‚Äôt use act() before, such as when the state update was inside an asynchronous function. As a result, you should be able to fix all the remaining act() warnings in your tests now.\nWe‚Äôve heard there wasn‚Äôt enough information about how to write tests with act(). The new Testing Recipes guide describes common scenarios, and how act() can help you write good tests. These examples use vanilla DOM APIs, but you can also use React Testing Library to reduce the boilerplate code. Many of its methods already use act() internally.\nPlease let us know on the issue tracker if you bump into any other scenarios where act() doesn‚Äôt work well for you, and we‚Äôll try to help.\nPerformance Measurements with &lt;React.Profiler&gt; \nIn React 16.5, we introduced a new React Profiler for DevTools that helps find performance bottlenecks in your application. In React 16.9, we are also adding a programmatic way to gather measurements called &lt;React.Profiler&gt;. We expect that most smaller apps won‚Äôt use it, but it can be handy to track performance regressions over time in larger apps.\nThe &lt;Profiler&gt; measures how often a React application renders and what the ‚Äúcost‚Äù of rendering is. Its purpose is to help identify parts of an application that are slow and may benefit from optimizations such as memoization.\nA &lt;Profiler&gt; can be added anywhere in a React tree to measure the cost of rendering that part of the tree.\nIt requires two props: an id (string) and an onRender callback (function) which React calls any time a component within the tree ‚Äúcommits‚Äù an update.\nrender(\n  &lt;Profiler id=\"application\" onRender={onRenderCallback}&gt;\n    &lt;App&gt;\n      &lt;Navigation {...props} /&gt;\n      &lt;Main {...props} /&gt;\n    &lt;/App&gt;\n  &lt;/Profiler&gt;\n);\n To learn more about the Profiler and the parameters passed to the onRender callback, check out the Profiler docs.\n\nNote:\nProfiling adds some additional overhead, so it is disabled in the production build.\nTo opt into production profiling, React provides a special production build with profiling enabled.\nRead more about how to use this build at fb.me/react-profiling.\n\nNotable Bugfixes \nThis release contains a few other notable improvements:\n\n\nA crash when calling findDOMNode() inside a &lt;Suspense&gt; tree has been fixed.\n\n\nA memory leak caused by retaining deleted subtrees has been fixed too.\n\n\nAn infinite loop caused by setState in useEffect now logs an error. (This is similar to the error you see when you call setState in componentDidUpdate in a class.)\n\n\nWe‚Äôre thankful to all the contributors who helped surface and fix these and other issues. You can find the full changelog below.\nAn Update to the Roadmap \nIn November 2018, we have posted this roadmap for the 16.x releases:\n\nA minor 16.x release with React Hooks (past estimate: Q1 2019)\nA minor 16.x release with Concurrent Mode (past estimate: Q2 2019)\nA minor 16.x release with Suspense for Data Fetching (past estimate: mid 2019)\n\nThese estimates were too optimistic, and we‚Äôve needed to adjust them.\ntldr: We shipped Hooks on time, but we‚Äôre regrouping Concurrent Mode and Suspense for Data Fetching into a single release that we intend to release later this year.\nIn February, we shipped a stable 16.8 release including React Hooks, with React Native support coming a month later. However, we underestimated the follow-up work for this release, including the lint rules, developer tools, examples, and more documentation. This shifted the timeline by a few months.\nNow that React Hooks are rolled out, the work on Concurrent Mode and Suspense for Data Fetching is in full swing. The new Facebook website that‚Äôs currently in active development is built on top of these features. Testing them with real code helped discover and address many issues before they can affect the open source users. Some of these fixes involved an internal redesign of these features, which has also caused the timeline to slip.\nWith this new understanding, here‚Äôs what we plan to do next.\nOne Release Instead of Two \nConcurrent Mode and Suspense power the new Facebook website that‚Äôs in active development, so we are confident that they‚Äôre close to a stable state technically. We also now better understand the concrete steps before they are ready for open source adoption.\nOriginally we thought we would split Concurrent Mode and Suspense for Data Fetching into two releases. We‚Äôve found that this sequencing is confusing to explain because these features are more related than we thought at first. So we plan to release support for both Concurrent Mode and Suspense for Data Fetching in a single combined release instead.\nWe don‚Äôt want to overpromise the release date again. Given that we rely on both of them in production code, we expect to provide a 16.x release with opt-in support for them this year.\nAn Update on Data Fetching \nWhile React is not opinionated about how you fetch data, the first release of Suspense for Data Fetching will likely focus on integrating with opinionated data fetching libraries. For example, at Facebook we are using upcoming Relay APIs that integrate with Suspense. We will document how other opinionated libraries like Apollo can support a similar integration.\nIn the first release, we don‚Äôt intend to focus on the ad-hoc ‚Äúfire an HTTP request‚Äù solution we used in earlier demos (also known as ‚ÄúReact Cache‚Äù). However, we expect that both we and the React community will be exploring that space in the months after the initial release.\nAn Update on Server Rendering \nWe have started the work on the new Suspense-capable server renderer, but we don‚Äôt expect it to be ready for the initial release of Concurrent Mode. This release will, however, provide a temporary solution that lets the existing server renderer emit HTML for Suspense fallbacks immediately, and then render their real content on the client. This is the solution we are currently using at Facebook ourselves until the streaming renderer is ready.\nWhy Is It Taking So Long? \nWe‚Äô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.\nInstallation \nReact \nReact v16.9.0 is available on the npm registry.\nTo install React 16 with Yarn, run:\nyarn add react@^16.9.0 react-dom@^16.9.0\nTo install React 16 with npm, run:\nnpm install --save react@^16.9.0 react-dom@^16.9.0\nWe also provide UMD builds of React via a CDN:\n&lt;script crossorigin src=\"https://unpkg.com/react@16/umd/react.production.min.js\"&gt;&lt;/script&gt;\n&lt;script crossorigin src=\"https://unpkg.com/react-dom@16/umd/react-dom.production.min.js\"&gt;&lt;/script&gt;\nRefer to the documentation for detailed installation instructions.\nChangelog \nReact \n\nAdd &lt;React.Profiler&gt; API for gathering performance measurements programmatically. (@bvaughn in #15172)\nRemove unstable_ConcurrentMode in favor of unstable_createRoot. (@acdlite in #15532)\n\nReact DOM \n\nDeprecate old names for the UNSAFE_* lifecycle methods. (@bvaughn in #15186 and @threepointone in #16103)\nDeprecate javascript: URLs as a common attack surface. (@sebmarkbage in #15047)\nDeprecate uncommon ‚Äúmodule pattern‚Äù (factory) components. (@sebmarkbage in #15145)\nAdd support for the disablePictureInPicture attribute on &lt;video&gt;. (@eek in #15334)\nAdd support for onLoad event for &lt;embed&gt;. (@cherniavskii in #15614)\nAdd support for editing useState state from DevTools. (@bvaughn in #14906)\nAdd support for toggling Suspense from DevTools. (@gaearon in #15232)\nWarn when setState is called from useEffect, creating a loop. (@gaearon in #15180)\nFix a memory leak. (@paulshen in #16115)\nFix a crash inside findDOMNode for components wrapped in &lt;Suspense&gt;. (@acdlite in #15312)\nFix pending effects from being flushed too late. (@acdlite in #15650)\nFix incorrect argument order in a warning message. (@brickspert in #15345)\nFix hiding Suspense fallback nodes when there is an !important style. (@acdlite in #15861 and #15882)\nSlightly improve hydration performance. (@bmeurer in #15998)\n\nReact DOM Server \n\nFix incorrect output for camelCase custom CSS property names. (@bedakb in #16167)\n\nReact Test Utilities and Test Renderer \n\nAdd act(async () =&gt; ...) for testing asynchronous state updates. (@threepointone in #14853)\nAdd support for nesting act from different renderers. (@threepointone in #16039 and #16042)\nWarn in Strict Mode if effects are scheduled outside an act() call. (@threepointone in #15763 and #16041)\nWarn when using act from the wrong renderer. (@threepointone in #15756)\n",
        ),
        content: Some(
            "<p>Today we are releasing React 16.9. It contains several new features, bugfixes, and new deprecation warnings to help prepare for a future major release. </p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#new-deprecations\" rel=\"noopener noreferrer\"></a>New Deprecations </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#renaming-unsafe-lifecycle-methods\" rel=\"noopener noreferrer\"></a>Renaming Unsafe Lifecycle Methods </h3>\n<p><a href=\"https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html\" rel=\"noopener noreferrer\">Over a year ago</a>, we announced that unsafe lifecycle methods are getting renamed:</p>\n<ul>\n<li><code>componentWillMount</code> ‚Üí <code>UNSAFE_componentWillMount</code></li>\n<li><code>componentWillReceiveProps</code> ‚Üí <code>UNSAFE_componentWillReceiveProps</code></li>\n<li><code>componentWillUpdate</code> ‚Üí <code>UNSAFE_componentWillUpdate</code></li>\n</ul>\n<p><strong>React 16.9 does not contain breaking changes, and the old names continue to work in this release.</strong> But you will now see a warning when using any of the old names:</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>As the warning suggests, there are usually <a href=\"https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#migrating-from-legacy-lifecycles\" rel=\"noopener noreferrer\">better approaches</a> for each of the unsafe methods. However, maybe you don‚Äôt have the time to migrate or test these components. In that case, we recommend running a <a href=\"https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb\" rel=\"noopener noreferrer\">‚Äúcodemod‚Äù</a> script that renames them automatically:</p>\n<div><pre><code><span>cd</span> your_project\nnpx react-codemod rename-unsafe-lifecycles</code></pre></div>\n<p><em>(Note that it says <code>npx</code>, not <code>npm</code>. <code>npx</code> is a utility that comes with Node 6+ by default.)</em></p>\n<p>Running this codemod will replace the old names like <code>componentWillMount</code> with the new names like <code>UNSAFE_componentWillMount</code>:</p>\n<p><img src=\"https://i.imgur.com/Heyvcyi.gif\" alt=\"Codemod in action\"></p>\n<p>The new names like <code>UNSAFE_componentWillMount</code> <strong>will keep working in both React 16.9 and in React 17.x</strong>. However, the new <code>UNSAFE_</code> prefix will help components with problematic patterns stand out during the code review and debugging sessions. (If you‚Äôd like, you can further discourage their use inside your app with the opt-in <a href=\"https://reactjs.org/docs/strict-mode.html\" rel=\"noopener noreferrer\">Strict Mode</a>.)</p>\n<blockquote>\n<p>Note</p>\n<p>Learn more about our <a href=\"https://reactjs.org/docs/faq-versioning.html#commitment-to-stability\" rel=\"noopener noreferrer\">versioning policy and commitment to stability</a>.</p>\n</blockquote>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-javascript-urls\" rel=\"noopener noreferrer\"></a>Deprecating <code>javascript:</code> URLs </h3>\n<p>URLs starting with <code>javascript:</code> are a dangerous attack surface because it‚Äôs easy to accidentally include unsanitized output in a tag like <code>&lt;a href&gt;</code> and create a security hole:</p>\n<div><pre><code><span>const</span> userProfile <span>=</span> <span>{</span>\n  website<span>:</span> <span>\"javascript: alert(\'you got hacked\')\"</span><span>,</span>\n<span>}</span><span>;</span>\n<span>// This will now warn:</span>\n<span><span><span>&lt;</span>a</span> <span>href</span><span><span>=</span><span>{</span>userProfile<span>.</span>website<span>}</span></span><span>&gt;</span></span><span>Profile</span><span><span><span>&lt;/</span>a</span><span>&gt;</span></span></code></pre></div>\n<p><strong>In React 16.9,</strong> this pattern continues to work, but it will log a warning. If you use <code>javascript:</code> URLs for logic, try to use React event handlers instead. (As a last resort, you can circumvent the protection with <a href=\"https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml\" rel=\"noopener noreferrer\"><code>dangerouslySetInnerHTML</code></a>, but it is highly discouraged and often leads to security holes.)</p>\n<p><strong>In a future major release,</strong> React will throw an error if it encounters a <code>javascript:</code> URL.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-factory-components\" rel=\"noopener noreferrer\"></a>Deprecating ‚ÄúFactory‚Äù Components </h3>\n<p>Before compiling JavaScript classes with Babel became popular, React had support for a ‚Äúfactory‚Äù component that returns an object with a <code>render</code> method:</p>\n<div><pre><code><span>function</span> <span>FactoryComponent</span><span>(</span><span>)</span> <span>{</span>\n  <span>return</span> <span>{</span> <span>render</span><span>(</span><span>)</span> <span>{</span> <span>return</span> <span><span><span>&lt;</span>div</span> <span>/&gt;</span></span><span>;</span> <span>}</span> <span>}</span>\n<span>}</span></code></pre></div>\n<p>This pattern is confusing because it looks too much like a function component ‚Äî but it isn‚Äôt one. (A function component would just return the <code>&lt;div /&gt;</code> in the above example.)</p>\n<p>This pattern was almost never used in the wild, and supporting it causes React to be slightly larger and slower than necessary. So we are deprecating this pattern in 16.9 and logging a warning if it‚Äôs encountered. If you rely on it, adding <code>FactoryComponent.prototype = React.Component.prototype</code> can serve as a workaround. Alternatively, you can convert it to either a class or a function component.</p>\n<p>We don‚Äôt expect most codebases to be affected by this.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#new-features\" rel=\"noopener noreferrer\"></a>New Features </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#async-act-for-testing\" rel=\"noopener noreferrer\"></a>Async <a href=\"https://reactjs.org/docs/test-utils.html#act\" rel=\"noopener noreferrer\"><code>act()</code></a> for Testing </h3>\n<p><a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html\" rel=\"noopener noreferrer\">React 16.8</a> introduced a new testing utility called <a href=\"https://reactjs.org/docs/test-utils.html#act\" rel=\"noopener noreferrer\"><code>act()</code></a> to help you write tests that better match the browser behavior. For example, multiple state updates inside a single <code>act()</code> get batched. This matches how React already works when handling real browser events, and helps prepare your components for the future in which React will batch updates more often.</p>\n<p>However, in 16.8 <code>act()</code> only supported synchronous functions. Sometimes, you might have seen a warning like this in a test but <a href=\"https://github.com/facebook/react/issues/14769\" rel=\"noopener noreferrer\">could not easily fix it</a>:</p>\n<div><pre><code>An update to SomeComponent inside a test was not wrapped in act(...).</code></pre></div>\n<p><strong>In React 16.9, <code>act()</code> also accepts asynchronous functions,</strong> and you can <code>await</code> its call:</p>\n<div><pre><code><span>await</span> <span>act</span><span>(</span><span>async</span> <span>(</span><span>)</span> <span>=&gt;</span> <span>{</span>\n  <span>// ...</span>\n<span>}</span><span>)</span><span>;</span></code></pre></div>\n<p>This solves the remaining cases where you couldn‚Äôt use <code>act()</code> before, such as when the state update was inside an asynchronous function. As a result, <strong>you should be able to fix all the remaining <code>act()</code> warnings in your tests now.</strong></p>\n<p>We‚Äôve heard there wasn‚Äôt enough information about how to write tests with <code>act()</code>. The new <a href=\"https://reactjs.org/docs/testing-recipes.html\" rel=\"noopener noreferrer\">Testing Recipes</a> guide describes common scenarios, and how <code>act()</code> can help you write good tests. These examples use vanilla DOM APIs, but you can also use <a href=\"https://testing-library.com/docs/react-testing-library/intro\" rel=\"noopener noreferrer\">React Testing Library</a> to reduce the boilerplate code. Many of its methods already use <code>act()</code> internally.</p>\n<p>Please let us know <a href=\"https://github.com/facebook/react/issues\" rel=\"noopener noreferrer\">on the issue tracker</a> if you bump into any other scenarios where <code>act()</code> doesn‚Äôt work well for you, and we‚Äôll try to help.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#performance-measurements-with-reactprofiler\" rel=\"noopener noreferrer\"></a>Performance Measurements with <a href=\"https://reactjs.org/docs/profiler.html\" rel=\"noopener noreferrer\"><code>&lt;React.Profiler&gt;</code></a> </h3>\n<p>In React 16.5, we introduced a new <a href=\"https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html\" rel=\"noopener noreferrer\">React Profiler for DevTools</a> that helps find performance bottlenecks in your application. <strong>In React 16.9, we are also adding a <em>programmatic</em> way to gather measurements</strong> called <code>&lt;React.Profiler&gt;</code>. We expect that most smaller apps won‚Äôt use it, but it can be handy to track performance regressions over time in larger apps.</p>\n<p>The <code>&lt;Profiler&gt;</code> measures how often a React application renders and what the ‚Äúcost‚Äù of rendering is. Its purpose is to help identify parts of an application that are slow and may benefit from <a href=\"https://reactjs.org/docs/hooks-faq.html#how-to-memoize-calculations\" rel=\"noopener noreferrer\">optimizations such as memoization</a>.</p>\n<p>A <code>&lt;Profiler&gt;</code> can be added anywhere in a React tree to measure the cost of rendering that part of the tree.\nIt requires two props: an <code>id</code> (string) and an <a href=\"https://reactjs.org/docs/profiler.html#onrender-callback\" rel=\"noopener noreferrer\"><code>onRender</code> callback</a> (function) which React calls any time a component within the tree ‚Äúcommits‚Äù an update.</p>\n<div><pre><code><span>render</span><span>(</span>\n<span>  <span><span><span>&lt;</span>Profiler</span> <span>id</span><span><span>=</span><span>\"</span>application<span>\"</span></span> <span>onRender</span><span><span>=</span><span>{</span>onRenderCallback<span>}</span></span><span>&gt;</span></span><span></span>\n</span><span>    </span><span><span><span>&lt;</span>App</span><span>&gt;</span></span><span></span>\n<span>      </span><span><span><span>&lt;</span>Navigation</span> <span><span>{</span><span>...</span><span>props</span><span>}</span></span> <span>/&gt;</span></span><span></span>\n<span>      </span><span><span><span>&lt;</span>Main</span> <span><span>{</span><span>...</span><span>props</span><span>}</span></span> <span>/&gt;</span></span><span></span>\n<span>    </span><span><span><span>&lt;/</span>App</span><span>&gt;</span></span><span></span>\n<span><span>  </span><span><span><span>&lt;/</span>Profiler</span><span>&gt;</span></span>\n</span><span>)</span><span>;</span></code></pre></div>\n<p> To learn more about the <code>Profiler</code> and the parameters passed to the <code>onRender</code> callback, check out <a href=\"https://reactjs.org/docs/profiler.html\" rel=\"noopener noreferrer\">the <code>Profiler</code> docs</a>.</p>\n<blockquote>\n<p>Note:</p>\n<p>Profiling adds some additional overhead, so <strong>it is disabled in <a href=\"https://reactjs.org/docs/optimizing-performance.html#use-the-production-build\" rel=\"noopener noreferrer\">the production build</a></strong>.</p>\n<p>To opt into production profiling, React provides a special production build with profiling enabled.\nRead more about how to use this build at <a href=\"https://fb.me/react-profiling\" rel=\"noopener noreferrer\">fb.me/react-profiling</a>.</p>\n</blockquote>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#notable-bugfixes\" rel=\"noopener noreferrer\"></a>Notable Bugfixes </h2>\n<p>This release contains a few other notable improvements:</p>\n<ul>\n<li>\n<p>A crash when calling <code>findDOMNode()</code> inside a <code>&lt;Suspense&gt;</code> tree <a href=\"https://github.com/facebook/react/pull/15312\" rel=\"noopener noreferrer\">has been fixed</a>.</p>\n</li>\n<li>\n<p>A memory leak caused by retaining deleted subtrees <a href=\"https://github.com/facebook/react/pull/16115\" rel=\"noopener noreferrer\">has been fixed</a> too.</p>\n</li>\n<li>\n<p>An infinite loop caused by <code>setState</code> in <code>useEffect</code> now <a href=\"https://github.com/facebook/react/pull/15180\" rel=\"noopener noreferrer\">logs an error</a>. (This is similar to the error you see when you call <code>setState</code> in <code>componentDidUpdate</code> in a class.)</p>\n</li>\n</ul>\n<p>We‚Äôre thankful to all the contributors who helped surface and fix these and other issues. You can find the full changelog <a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#changelog\" rel=\"noopener noreferrer\">below</a>.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an-update-to-the-roadmap\" rel=\"noopener noreferrer\"></a>An Update to the Roadmap </h2>\n<p>In <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html\" rel=\"noopener noreferrer\">November 2018</a>, we have posted this roadmap for the 16.x releases:</p>\n<ul>\n<li>A minor 16.x release with React Hooks (past estimate: Q1 2019)</li>\n<li>A minor 16.x release with Concurrent Mode (past estimate: Q2 2019)</li>\n<li>A minor 16.x release with Suspense for Data Fetching (past estimate: mid 2019)</li>\n</ul>\n<p>These estimates were too optimistic, and we‚Äôve needed to adjust them.</p>\n<p><strong>tldr:</strong> We shipped Hooks on time, but we‚Äôre regrouping Concurrent Mode and Suspense for Data Fetching into a single release that we intend to release later this year.</p>\n<p>In February, we <a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html\" rel=\"noopener noreferrer\">shipped a stable 16.8 release</a> including React Hooks, with React Native support coming <a href=\"https://facebook.github.io/react-native/blog/2019/03/12/releasing-react-native-059\" rel=\"noopener noreferrer\">a month later</a>. However, we underestimated the follow-up work for this release, including the lint rules, developer tools, examples, and more documentation. This shifted the timeline by a few months.</p>\n<p>Now that React Hooks are rolled out, the work on Concurrent Mode and Suspense for Data Fetching is in full swing. The <a href=\"https://twitter.com/facebook/status/1123322299418124289\" rel=\"noopener noreferrer\">new Facebook website that‚Äôs currently in active development</a> is built on top of these features. Testing them with real code helped discover and address many issues before they can affect the open source users. Some of these fixes involved an internal redesign of these features, which has also caused the timeline to slip.</p>\n<p>With this new understanding, here‚Äôs what we plan to do next.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#one-release-instead-of-two\" rel=\"noopener noreferrer\"></a>One Release Instead of Two </h3>\n<p>Concurrent Mode and Suspense <a href=\"https://developers.facebook.com/videos/2019/building-the-new-facebookcom-with-react-graphql-and-relay/\" rel=\"noopener noreferrer\">power the new Facebook website</a> that‚Äôs in active development, so we are confident that they‚Äôre close to a stable state technically. We also now better understand the concrete steps before they are ready for open source adoption.</p>\n<p>Originally we thought we would split Concurrent Mode and Suspense for Data Fetching into two releases. We‚Äôve found that this sequencing is confusing to explain because these features are more related than we thought at first. So we plan to release support for both Concurrent Mode and Suspense for Data Fetching in a single combined release instead.</p>\n<p>We don‚Äôt want to overpromise the release date again. Given that we rely on both of them in production code, we expect to provide a 16.x release with opt-in support for them this year.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an-update-on-data-fetching\" rel=\"noopener noreferrer\"></a>An Update on Data Fetching </h3>\n<p>While React is not opinionated about how you fetch data, the first release of Suspense for Data Fetching will likely focus on integrating with <em>opinionated data fetching libraries</em>. For example, at Facebook we are using upcoming Relay APIs that integrate with Suspense. We will document how other opinionated libraries like Apollo can support a similar integration.</p>\n<p>In the first release, we <em>don‚Äôt</em> intend to focus on the ad-hoc ‚Äúfire an HTTP request‚Äù solution we used in earlier demos (also known as ‚ÄúReact Cache‚Äù). However, we expect that both we and the React community will be exploring that space in the months after the initial release.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#an-update-on-server-rendering\" rel=\"noopener noreferrer\"></a>An Update on Server Rendering </h3>\n<p>We have started the work on the <a href=\"https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#suspense-for-server-rendering\" rel=\"noopener noreferrer\">new Suspense-capable server renderer</a>, but we <em>don‚Äôt</em> expect it to be ready for the initial release of Concurrent Mode. This release will, however, provide a temporary solution that lets the existing server renderer emit HTML for Suspense fallbacks immediately, and then render their real content on the client. This is the solution we are currently using at Facebook ourselves until the streaming renderer is ready.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#why-is-it-taking-so-long\" rel=\"noopener noreferrer\"></a>Why Is It Taking So Long? </h3>\n<p>We‚Äôve shipped the individual pieces leading up to Concurrent Mode as they became stable, including <a href=\"https://reactjs.org/blog/2018/03/29/react-v-16-3.html\" rel=\"noopener noreferrer\">new context API</a>, <a href=\"https://reactjs.org/blog/2018/10/23/react-v-16-6.html\" rel=\"noopener noreferrer\">lazy loading with Suspense</a>, and <a href=\"https://reactjs.org/blog/2019/02/06/react-v16.8.0.html\" rel=\"noopener noreferrer\">Hooks</a>. We are also eager to release the other missing parts, but <a href=\"https://reactjs.org/docs/design-principles.html#dogfooding\" rel=\"noopener noreferrer\">trying them at scale</a> 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 <a href=\"https://twitter.com/reactjs\" rel=\"noopener noreferrer\">Twitter</a> and in our <a href=\"https://github.com/facebook/react/issues\" rel=\"noopener noreferrer\">issue tracker</a>.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#installation\" rel=\"noopener noreferrer\"></a>Installation </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#react\" rel=\"noopener noreferrer\"></a>React </h3>\n<p>React v16.9.0 is available on the npm registry.</p>\n<p>To install React 16 with Yarn, run:</p>\n<div><pre><code>yarn add react@^16.9.0 react-dom@^16.9.0</code></pre></div>\n<p>To install React 16 with npm, run:</p>\n<div><pre><code><span>npm</span> <span>install</span> --save react@^16.9.0 react-dom@^16.9.0</code></pre></div>\n<p>We also provide UMD builds of React via a CDN:</p>\n<div><pre><code><span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react@16/umd/react.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span>\n<span><span><span>&lt;</span>script</span> <span>crossorigin</span> <span>src</span><span><span>=</span><span>\"</span>https://unpkg.com/react-dom@16/umd/react-dom.production.min.js<span>\"</span></span><span>&gt;</span></span><span></span><span><span><span>&lt;/</span>script</span><span>&gt;</span></span></code></pre></div>\n<p>Refer to the documentation for <a href=\"https://reactjs.org/docs/installation.html\" rel=\"noopener noreferrer\">detailed installation instructions</a>.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#changelog\" rel=\"noopener noreferrer\"></a>Changelog </h2>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#react\" rel=\"noopener noreferrer\"></a>React </h3>\n<ul>\n<li>Add <code>&lt;React.Profiler&gt;</code> API for gathering performance measurements programmatically. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/15172\" rel=\"noopener noreferrer\">#15172</a>)</li>\n<li>Remove <code>unstable_ConcurrentMode</code> in favor of <code>unstable_createRoot</code>. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15532\" rel=\"noopener noreferrer\">#15532</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#react-dom\" rel=\"noopener noreferrer\"></a>React DOM </h3>\n<ul>\n<li>Deprecate old names for the <code>UNSAFE_*</code> lifecycle methods. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/15186\" rel=\"noopener noreferrer\">#15186</a> and <a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/16103\" rel=\"noopener noreferrer\">#16103</a>)</li>\n<li>Deprecate <code>javascript:</code> URLs as a common attack surface. (<a href=\"https://github.com/sebmarkbage\" rel=\"noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/15047\" rel=\"noopener noreferrer\">#15047</a>)</li>\n<li>Deprecate uncommon ‚Äúmodule pattern‚Äù (factory) components. (<a href=\"https://github.com/sebmarkbage\" rel=\"noopener noreferrer\">@sebmarkbage</a> in <a href=\"https://github.com/facebook/react/pull/15145\" rel=\"noopener noreferrer\">#15145</a>)</li>\n<li>Add support for the <code>disablePictureInPicture</code> attribute on <code>&lt;video&gt;</code>. (<a href=\"https://github.com/eek\" rel=\"noopener noreferrer\">@eek</a> in <a href=\"https://github.com/facebook/react/pull/15334\" rel=\"noopener noreferrer\">#15334</a>)</li>\n<li>Add support for <code>onLoad</code> event for <code>&lt;embed&gt;</code>. (<a href=\"https://github.com/cherniavskii\" rel=\"noopener noreferrer\">@cherniavskii</a> in <a href=\"https://github.com/facebook/react/pull/15614\" rel=\"noopener noreferrer\">#15614</a>)</li>\n<li>Add support for editing <code>useState</code> state from DevTools. (<a href=\"https://github.com/bvaughn\" rel=\"noopener noreferrer\">@bvaughn</a> in <a href=\"https://github.com/facebook/react/pull/14906\" rel=\"noopener noreferrer\">#14906</a>)</li>\n<li>Add support for toggling Suspense from DevTools. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/15232\" rel=\"noopener noreferrer\">#15232</a>)</li>\n<li>Warn when <code>setState</code> is called from <code>useEffect</code>, creating a loop. (<a href=\"https://github.com/gaearon\" rel=\"noopener noreferrer\">@gaearon</a> in <a href=\"https://github.com/facebook/react/pull/15180\" rel=\"noopener noreferrer\">#15180</a>)</li>\n<li>Fix a memory leak. (<a href=\"https://github.com/paulshen\" rel=\"noopener noreferrer\">@paulshen</a> in <a href=\"https://github.com/facebook/react/pull/16115\" rel=\"noopener noreferrer\">#16115</a>)</li>\n<li>Fix a crash inside <code>findDOMNode</code> for components wrapped in <code>&lt;Suspense&gt;</code>. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15312\" rel=\"noopener noreferrer\">#15312</a>)</li>\n<li>Fix pending effects from being flushed too late. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15650\" rel=\"noopener noreferrer\">#15650</a>)</li>\n<li>Fix incorrect argument order in a warning message. (<a href=\"https://github.com/brickspert\" rel=\"noopener noreferrer\">@brickspert</a> in <a href=\"https://github.com/facebook/react/pull/15345\" rel=\"noopener noreferrer\">#15345</a>)</li>\n<li>Fix hiding Suspense fallback nodes when there is an <code>!important</code> style. (<a href=\"https://github.com/acdlite\" rel=\"noopener noreferrer\">@acdlite</a> in <a href=\"https://github.com/facebook/react/pull/15861\" rel=\"noopener noreferrer\">#15861</a> and <a href=\"https://github.com/facebook/react/pull/15882\" rel=\"noopener noreferrer\">#15882</a>)</li>\n<li>Slightly improve hydration performance. (<a href=\"https://github.com/bmeurer\" rel=\"noopener noreferrer\">@bmeurer</a> in <a href=\"https://github.com/facebook/react/pull/15998\" rel=\"noopener noreferrer\">#15998</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#react-dom-server\" rel=\"noopener noreferrer\"></a>React DOM Server </h3>\n<ul>\n<li>Fix incorrect output for camelCase custom CSS property names. (<a href=\"https://github.com/bedakb\" rel=\"noopener noreferrer\">@bedakb</a> in <a href=\"https://github.com/facebook/react/pull/16167\" rel=\"noopener noreferrer\">#16167</a>)</li>\n</ul>\n<h3><a href=\"https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#react-test-utilities-and-test-renderer\" rel=\"noopener noreferrer\"></a>React Test Utilities and Test Renderer </h3>\n<ul>\n<li>Add <code>act(async () =&gt; ...)</code> for testing asynchronous state updates. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/14853\" rel=\"noopener noreferrer\">#14853</a>)</li>\n<li>Add support for nesting <code>act</code> from different renderers. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/16039\" rel=\"noopener noreferrer\">#16039</a> and <a href=\"https://github.com/facebook/react/pull/16042\" rel=\"noopener noreferrer\">#16042</a>)</li>\n<li>Warn in Strict Mode if effects are scheduled outside an <code>act()</code> call. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/15763\" rel=\"noopener noreferrer\">#15763</a> and <a href=\"https://github.com/facebook/react/pull/16041\" rel=\"noopener noreferrer\">#16041</a>)</li>\n<li>Warn when using <code>act</code> from the wrong renderer. (<a href=\"https://github.com/threepointone\" rel=\"noopener noreferrer\">@threepointone</a> in <a href=\"https://github.com/facebook/react/pull/15756\" rel=\"noopener noreferrer\">#15756</a>)</li>\n</ul>",
        ),
        media_type: Some(
            MediaType {
                mime: "image/*",
            },
        ),
        media_link: Some(
            "https://i.imgur.com/sngxSML.png",
        ),
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/08/15/new-react-devtools.html",
        link: "https://reactjs.org/blog/2019/08/15/new-react-devtools.html",
        title: "Introducing the New React DevTools",
        date: 2019-08-15T00:00:00Z,
        summary: Some(
            "We are excited to announce a new release of the React Developer Tools, available today in Chrome, Firefox, and (Chromium) Edge!\nWhat‚Äôs changed? \nA lot has changed in version 4!\nAt a high level, this new version should offer significant performance gains and an improved navigation experience.\nIt also offers full support for React Hooks, including inspecting nested objects.\n\n  \n\n  \n    \n      \n    \n  \n\n  \n    \nVisit the interactive tutorial to try out the new version or see the changelog for demo videos and more details.\nWhich versions of React are supported? \nreact-dom\n\n0-14.x: Not supported\n15.x: Supported (except for the new component filters feature)\n16.x: Supported\n\nreact-native\n\n0-0.61: Not supported\n0.62: Will be supported (when 0.62 is released)\n\nHow do I get the new DevTools? \nReact DevTools is available as an extension for Chrome and Firefox.\nIf you have already installed the extension, it should update automatically within the next couple of hours.\nIf you use the standalone shell (e.g. in React Native or Safari), you can install the new version from NPM:\nnpm install -g react-devtools@^4\nWhere did all of the DOM elements go? \nThe new DevTools provides a way to filter components from the tree to make it easier to navigate deeply nested hierarchies.\nHost nodes (e.g. HTML &lt;div&gt;, React Native &lt;View&gt;) are hidden by default, but this filter can be disabled:\n\nHow do I get the old version back? \nIf you are working with React Native version 60 (or older) you can install the previous release of DevTools from NPM:\nnpm install --dev react-devtools@^3\nFor older versions of React DOM (v0.14 or earlier) you will need to build the extension from source:\n# Checkout the extension source\ngit clone https://github.com/facebook/react-devtools\n\ncd react-devtools\n\n# Checkout the previous release branch\ngit checkout v3\n\n# Install dependencies and build the unpacked extension\nyarn install\nyarn build:extension\n\n# Follow the on-screen instructions to complete installation\nThank you! \nWe‚Äôd like to thank everyone who tested the early release of DevTools version 4.\nYour feedback helped improve this initial release significantly.\nWe still have many exciting features planned and feedback is always welcome!\nPlease feel free to open a GitHub issue or tag @reactjs on Twitter.",
        ),
        content: Some(
            "<p>We are excited to announce a new release of the React Developer Tools, available today in Chrome, Firefox, and (Chromium) Edge!</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#whats-changed\" rel=\"noopener noreferrer\"></a>What‚Äôs changed? </h2>\n<p>A lot has changed in version 4!\nAt a high level, this new version should offer significant performance gains and an improved navigation experience.\nIt also offers full support for React Hooks, including inspecting nested objects.</p>\n<p>\n  <a href=\"https://reactjs.org/static/devtools-v4-screenshot-9552e88d7605ef4e547af89096a9225d-b9896.png\" rel=\"noopener noreferrer\">\n\n  <span>\n    <span>\n      <img alt=\"DevTools version 4 screenshot\" title=\"\" src=\"https://reactjs.org/static/devtools-v4-screenshot-9552e88d7605ef4e547af89096a9225d-acf85.png\">\n    </span>\n  </span>\n\n  </a>\n    </p>\n<p><a href=\"https://react-devtools-tutorial.now.sh/\" rel=\"noopener noreferrer\">Visit the interactive tutorial</a> to try out the new version or <a href=\"https://github.com/facebook/react/blob/master/packages/react-devtools/CHANGELOG.md#400-august-15-2019\" rel=\"noopener noreferrer\">see the changelog</a> for demo videos and more details.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#which-versions-of-react-are-supported\" rel=\"noopener noreferrer\"></a>Which versions of React are supported? </h2>\n<p><strong><code>react-dom</code></strong></p>\n<ul>\n<li><code>0</code>-<code>14.x</code>: Not supported</li>\n<li><code>15.x</code>: Supported (except for the new component filters feature)</li>\n<li><code>16.x</code>: Supported</li>\n</ul>\n<p><strong><code>react-native</code></strong></p>\n<ul>\n<li><code>0</code>-<code>0.61</code>: Not supported</li>\n<li><code>0.62</code>: Will be supported (when 0.62 is released)</li>\n</ul>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#how-do-i-get-the-new-devtools\" rel=\"noopener noreferrer\"></a>How do I get the new DevTools? </h2>\n<p>React DevTools is available as an extension for <a href=\"https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en\" rel=\"noopener noreferrer\">Chrome</a> and <a href=\"https://addons.mozilla.org/en-US/firefox/addon/react-devtools/\" rel=\"noopener noreferrer\">Firefox</a>.\nIf you have already installed the extension, it should update automatically within the next couple of hours.</p>\n<p>If you use the standalone shell (e.g. in React Native or Safari), you can install the new version <a href=\"https://www.npmjs.com/package/react-devtools\" rel=\"noopener noreferrer\">from NPM</a>:</p>\n<div><pre><code><span>npm</span> <span>install</span> -g react-devtools@^4</code></pre></div>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#where-did-all-of-the-dom-elements-go\" rel=\"noopener noreferrer\"></a>Where did all of the DOM elements go? </h2>\n<p>The new DevTools provides a way to filter components from the tree to make it easier to navigate deeply nested hierarchies.\nHost nodes (e.g. HTML <code>&lt;div&gt;</code>, React Native <code>&lt;View&gt;</code>) are <em>hidden by default</em>, but this filter can be disabled:</p>\n<p><img src=\"https://reactjs.org/devtools-component-filters-758ea5ee734afdda4cd0f6b43c74fbb4.gif\" alt=\"DevTools component filters\"></p>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#how-do-i-get-the-old-version-back\" rel=\"noopener noreferrer\"></a>How do I get the old version back? </h2>\n<p>If you are working with React Native version 60 (or older) you can install the previous release of DevTools from NPM:</p>\n<div><pre><code><span>npm</span> <span>install</span> --dev react-devtools@^3</code></pre></div>\n<p>For older versions of React DOM (v0.14 or earlier) you will need to build the extension from source:</p>\n<div><pre><code><span># Checkout the extension source</span>\n<span>git</span> clone https://github.com/facebook/react-devtools\n\n<span>cd</span> react-devtools\n\n<span># Checkout the previous release branch</span>\n<span>git</span> checkout v3\n\n<span># Install dependencies and build the unpacked extension</span>\nyarn <span>install</span>\nyarn build:extension\n\n<span># Follow the on-screen instructions to complete installation</span></code></pre></div>\n<h2><a href=\"https://reactjs.org/blog/2019/08/15/new-react-devtools.html#thank-you\" rel=\"noopener noreferrer\"></a>Thank you! </h2>\n<p>We‚Äôd like to thank everyone who tested the early release of DevTools version 4.\nYour feedback helped improve this initial release significantly.</p>\n<p>We still have many exciting features planned and feedback is always welcome!\nPlease feel free to open a <a href=\"https://github.com/facebook/react/issues/new?labels=Component:%20Developer%20Tools\" rel=\"noopener noreferrer\">GitHub issue</a> or tag <a href=\"https://twitter.com/reactjs\" rel=\"noopener noreferrer\">@reactjs on Twitter</a>.</p>",
        ),
        media_type: Some(
            MediaType {
                mime: "image/*",
            },
        ),
        media_link: Some(
            "https://reactjs.org/static/devtools-v4-screenshot-9552e88d7605ef4e547af89096a9225d-acf85.png",
        ),
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/10/22/react-release-channels.html",
        link: "https://reactjs.org/blog/2019/10/22/react-release-channels.html",
        title: "Preparing for the Future with React Prereleases",
        date: 2019-10-22T00:00:00Z,
        summary: Some(
            "To share upcoming changes with our partners in the React ecosystem, we‚Äôre establishing official prerelease channels. We hope this process will help us make changes to React with confidence, and give developers the opportunity to try out experimental features.\n\nThis post will be most relevant to developers who work on frameworks, libraries, or developer tooling. Developers who use React primarily to build user-facing applications should not need to worry about our prerelease channels.\n\nReact relies on a thriving open source community to file bug reports, open pull requests, and submit RFCs. To encourage feedback, we sometimes share special builds of React that include unreleased features.\nBecause the source of truth for React is our public GitHub repository, it‚Äôs always been possible to build a copy of React that includes the latest changes. However it‚Äôs much easier for developers to install React from npm, so we occasionally publish prerelease builds to the npm registry. A recent example is the 16.7 alpha, which included an early version of the Hooks API.\nWe would like to make it even easier for developers to test prerelease builds of React, so we‚Äôre formalizing our process with three separate release channels.\nRelease Channels \n\nThe information in this post is also available on our Release Channels page. We will update that document whenever there are changes to our release process.\n\nEach of React‚Äôs release channels is designed for a distinct use case:\n\nLatest is for stable, semver React releases. It‚Äôs what you get when you install React from npm. This is the channel you‚Äôre already using today. Use this for all user-facing React applications.\nNext tracks the master branch of the React source code repository. Think of these as release candidates for the next minor semver release. Use this for integration testing between React and third party projects.\nExperimental includes experimental APIs and features that aren‚Äôt available in the stable releases. These also track the master branch, but with additional feature flags turned on. Use this to try out upcoming features before they are released.\n\nAll releases are published to npm, but only Latest uses semantic versioning. Prereleases (those in the Next and Experimental channels) have versions generated from a hash of their contents, e.g. 0.0.0-1022ee0ec for Next and 0.0.0-experimental-1022ee0ec for Experimental.\nThe only officially supported release channel for user-facing applications is Latest. Next and Experimental releases are provided for testing purposes only, and we provide no guarantees that behavior won‚Äôt change between releases. They do not follow the semver protocol that we use for releases from Latest.\nBy publishing prereleases to the same registry that we use for stable releases, we are able to take advantage of the many tools that support the npm workflow, like unpkg and CodeSandbox.\nLatest Channel \nLatest is the channel used for stable React releases. It corresponds to the latest tag on npm. It is the recommended channel for all React apps that are shipped to real users.\nIf you‚Äôre not sure which channel you should use, it‚Äôs Latest. If you‚Äôre a React developer, this is what you‚Äôre already using.\nYou can expect updates to Latest to be extremely stable. Versions follow the semantic versioning scheme. Learn more about our commitment to stability and incremental migration in our versioning policy.\nNext Channel \nThe Next channel is a prerelease channel that tracks the master branch of the React repository. We use prereleases in the Next channel as release candidates for the Latest channel. You can think of Next as a superset of Latest that is updated more frequently.\nThe degree of change between the most recent Next release and the most recent Latest release is approximately the same as you would find between two minor semver releases. However, the Next channel does not conform to semantic versioning. You should expect occasional breaking changes between successive releases in the Next channel.\nDo not use prereleases in user-facing applications.\nReleases in Next are published with the next tag on npm. Versions are generated from a hash of the build‚Äôs contents, e.g. 0.0.0-1022ee0ec.\nUsing the Next Channel for Integration Testing \nThe Next channel is designed to support integration testing between React and other projects.\nAll changes to React go through extensive internal testing before they are released to the public. However, there are a myriad of environments and configurations used throughout the React ecosystem, and it‚Äôs not possible for us to test against every single one.\nIf you‚Äôre the author of a third party React framework, library, developer tool, or similar infrastructure-type project, you can help us keep React stable for your users and the entire React community by periodically running your test suite against the most recent changes. If you‚Äôre interested, follow these steps:\n\n\nSet up a cron job using your preferred continuous integration platform. Cron jobs are supported by both CircleCI and Travis CI.\n\n\nIn the cron job, update your React packages to the most recent React release in the Next channel, using next tag on npm. Using the npm cli:\nnpm update react@next react-dom@next\nOr yarn:\nyarn upgrade react@next react-dom@next\n\n\nRun your test suite against the updated packages.\n\n\nIf everything passes, great! You can expect that your project will work with the next minor React release.\n\n\nIf something breaks unexpectedly, please let us know by filing an issue.\n\n\nA project that uses this workflow is Next.js. (No pun intended! Seriously!) You can refer to their CircleCI configuration as an example.\nExperimental Channel \nLike Next, the Experimental channel is a prerelease channel that tracks the master branch of the React repository. Unlike Next, Experimental releases include additional features and APIs that are not ready for wider release.\nUsually, an update to Next is accompanied by a corresponding update to Experimental. They are based on the same source revision, but are built using a different set of feature flags.\nExperimental releases may be significantly different than releases to Next and Latest. Do not use Experimental releases in user-facing applications. You should expect frequent breaking changes between releases in the Experimental channel.\nReleases in Experimental are published with the experimental tag on npm. Versions are generated from a hash of the build‚Äôs contents, e.g. 0.0.0-experimental-1022ee0ec.\nWhat Goes Into an Experimental Release? \nExperimental features are ones that are not ready to be released to the wider public, and may change drastically before they are finalized. Some experiments may never be finalized ‚Äî the reason we have experiments is to test the viability of proposed changes.\nFor example, if the Experimental channel had existed when we announced Hooks, we would have released Hooks to the Experimental channel weeks before they were available in Latest.\nYou may find it valuable to run integration tests against Experimental. This is up to you. However, be advised that Experimental is even less stable than Next. We do not guarantee any stability between Experimental releases.\nHow Can I Learn More About Experimental Features? \nExperimental features may or may not be documented. Usually, experiments aren‚Äôt documented until they are close to shipping in Next or Stable.\nIf a feature is not documented, they may be accompanied by an RFC.\nWe will post to the React blog when we‚Äôre ready to announce new experiments, but that doesn‚Äôt mean we will publicize every experiment.\nYou can always refer to our public GitHub repository‚Äôs history for a comprehensive list of changes.",
        ),
        content: Some(
            "<p>To share upcoming changes with our partners in the React ecosystem, we‚Äôre establishing official prerelease channels. We hope this process will help us make changes to React with confidence, and give developers the opportunity to try out experimental features.</p>\n<blockquote>\n<p>This post will be most relevant to developers who work on frameworks, libraries, or developer tooling. Developers who use React primarily to build user-facing applications should not need to worry about our prerelease channels.</p>\n</blockquote>\n<p>React relies on a thriving open source community to file bug reports, open pull requests, and <a href=\"https://github.com/reactjs/rfcs\" rel=\"noopener noreferrer\">submit RFCs</a>. To encourage feedback, we sometimes share special builds of React that include unreleased features.</p>\n<p>Because the source of truth for React is our <a href=\"https://github.com/facebook/react\" rel=\"noopener noreferrer\">public GitHub repository</a>, it‚Äôs always been possible to build a copy of React that includes the latest changes. However it‚Äôs much easier for developers to install React from npm, so we occasionally publish prerelease builds to the npm registry. A recent example is the 16.7 alpha, which included an early version of the Hooks API.</p>\n<p>We would like to make it even easier for developers to test prerelease builds of React, so we‚Äôre formalizing our process with three separate release channels.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#release-channels\" rel=\"noopener noreferrer\"></a>Release Channels </h2>\n<blockquote>\n<p>The information in this post is also available on our <a href=\"https://reactjs.org/docs/release-channels.html\" rel=\"noopener noreferrer\">Release Channels</a> page. We will update that document whenever there are changes to our release process.</p>\n</blockquote>\n<p>Each of React‚Äôs release channels is designed for a distinct use case:</p>\n<ul>\n<li><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#latest-channel\" rel=\"noopener noreferrer\"><strong>Latest</strong></a> is for stable, semver React releases. It‚Äôs what you get when you install React from npm. This is the channel you‚Äôre already using today. <strong>Use this for all user-facing React applications.</strong></li>\n<li><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#next-channel\" rel=\"noopener noreferrer\"><strong>Next</strong></a> tracks the master branch of the React source code repository. Think of these as release candidates for the next minor semver release. Use this for integration testing between React and third party projects.</li>\n<li><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#experimental-channel\" rel=\"noopener noreferrer\"><strong>Experimental</strong></a> includes experimental APIs and features that aren‚Äôt available in the stable releases. These also track the master branch, but with additional feature flags turned on. Use this to try out upcoming features before they are released.</li>\n</ul>\n<p>All releases are published to npm, but only Latest uses <a href=\"https://reactjs.org/docs/faq-versioning.html\" rel=\"noopener noreferrer\">semantic versioning</a>. Prereleases (those in the Next and Experimental channels) have versions generated from a hash of their contents, e.g. <code>0.0.0-1022ee0ec</code> for Next and <code>0.0.0-experimental-1022ee0ec</code> for Experimental.</p>\n<p><strong>The only officially supported release channel for user-facing applications is Latest</strong>. Next and Experimental releases are provided for testing purposes only, and we provide no guarantees that behavior won‚Äôt change between releases. They do not follow the semver protocol that we use for releases from Latest.</p>\n<p>By publishing prereleases to the same registry that we use for stable releases, we are able to take advantage of the many tools that support the npm workflow, like <a href=\"https://unpkg.com/\" rel=\"noopener noreferrer\">unpkg</a> and <a href=\"https://codesandbox.io/\" rel=\"noopener noreferrer\">CodeSandbox</a>.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#latest-channel\" rel=\"noopener noreferrer\"></a>Latest Channel </h3>\n<p>Latest is the channel used for stable React releases. It corresponds to the <code>latest</code> tag on npm. It is the recommended channel for all React apps that are shipped to real users.</p>\n<p><strong>If you‚Äôre not sure which channel you should use, it‚Äôs Latest.</strong> If you‚Äôre a React developer, this is what you‚Äôre already using.</p>\n<p>You can expect updates to Latest to be extremely stable. Versions follow the semantic versioning scheme. Learn more about our commitment to stability and incremental migration in our <a href=\"https://reactjs.org/docs/faq-versioning.html\" rel=\"noopener noreferrer\">versioning policy</a>.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#next-channel\" rel=\"noopener noreferrer\"></a>Next Channel </h3>\n<p>The Next channel is a prerelease channel that tracks the master branch of the React repository. We use prereleases in the Next channel as release candidates for the Latest channel. You can think of Next as a superset of Latest that is updated more frequently.</p>\n<p>The degree of change between the most recent Next release and the most recent Latest release is approximately the same as you would find between two minor semver releases. However, <strong>the Next channel does not conform to semantic versioning.</strong> You should expect occasional breaking changes between successive releases in the Next channel.</p>\n<p><strong>Do not use prereleases in user-facing applications.</strong></p>\n<p>Releases in Next are published with the <code>next</code> tag on npm. Versions are generated from a hash of the build‚Äôs contents, e.g. <code>0.0.0-1022ee0ec</code>.</p>\n<h4><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#using-the-next-channel-for-integration-testing\" rel=\"noopener noreferrer\"></a>Using the Next Channel for Integration Testing </h4>\n<p>The Next channel is designed to support integration testing between React and other projects.</p>\n<p>All changes to React go through extensive internal testing before they are released to the public. However, there are a myriad of environments and configurations used throughout the React ecosystem, and it‚Äôs not possible for us to test against every single one.</p>\n<p>If you‚Äôre the author of a third party React framework, library, developer tool, or similar infrastructure-type project, you can help us keep React stable for your users and the entire React community by periodically running your test suite against the most recent changes. If you‚Äôre interested, follow these steps:</p>\n<ul>\n<li>\n<p>Set up a cron job using your preferred continuous integration platform. Cron jobs are supported by both <a href=\"https://circleci.com/docs/2.0/triggers/#scheduled-builds\" rel=\"noopener noreferrer\">CircleCI</a> and <a href=\"https://docs.travis-ci.com/user/cron-jobs/\" rel=\"noopener noreferrer\">Travis CI</a>.</p>\n</li>\n<li>\n<p>In the cron job, update your React packages to the most recent React release in the Next channel, using <code>next</code> tag on npm. Using the npm cli:</p>\n<div><pre><code>npm update react@next react-dom@next</code></pre></div>\n<p>Or yarn:</p>\n<div><pre><code>yarn upgrade react@next react-dom@next</code></pre></div>\n</li>\n<li>\n<p>Run your test suite against the updated packages.</p>\n</li>\n<li>\n<p>If everything passes, great! You can expect that your project will work with the next minor React release.</p>\n</li>\n<li>\n<p>If something breaks unexpectedly, please let us know by <a href=\"https://github.com/facebook/react/issues\" rel=\"noopener noreferrer\">filing an issue</a>.</p>\n</li>\n</ul>\n<p>A project that uses this workflow is Next.js. (No pun intended! Seriously!) You can refer to their <a href=\"https://github.com/zeit/next.js/blob/c0a1c0f93966fe33edd93fb53e5fafb0dcd80a9e/.circleci/config.yml\" rel=\"noopener noreferrer\">CircleCI configuration</a> as an example.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#experimental-channel\" rel=\"noopener noreferrer\"></a>Experimental Channel </h3>\n<p>Like Next, the Experimental channel is a prerelease channel that tracks the master branch of the React repository. Unlike Next, Experimental releases include additional features and APIs that are not ready for wider release.</p>\n<p>Usually, an update to Next is accompanied by a corresponding update to Experimental. They are based on the same source revision, but are built using a different set of feature flags.</p>\n<p>Experimental releases may be significantly different than releases to Next and Latest. <strong>Do not use Experimental releases in user-facing applications.</strong> You should expect frequent breaking changes between releases in the Experimental channel.</p>\n<p>Releases in Experimental are published with the <code>experimental</code> tag on npm. Versions are generated from a hash of the build‚Äôs contents, e.g. <code>0.0.0-experimental-1022ee0ec</code>.</p>\n<h4><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#what-goes-into-an-experimental-release\" rel=\"noopener noreferrer\"></a>What Goes Into an Experimental Release? </h4>\n<p>Experimental features are ones that are not ready to be released to the wider public, and may change drastically before they are finalized. Some experiments may never be finalized ‚Äî the reason we have experiments is to test the viability of proposed changes.</p>\n<p>For example, if the Experimental channel had existed when we announced Hooks, we would have released Hooks to the Experimental channel weeks before they were available in Latest.</p>\n<p>You may find it valuable to run integration tests against Experimental. This is up to you. However, be advised that Experimental is even less stable than Next. <strong>We do not guarantee any stability between Experimental releases.</strong></p>\n<h4><a href=\"https://reactjs.org/blog/2019/10/22/react-release-channels.html#how-can-i-learn-more-about-experimental-features\" rel=\"noopener noreferrer\"></a>How Can I Learn More About Experimental Features? </h4>\n<p>Experimental features may or may not be documented. Usually, experiments aren‚Äôt documented until they are close to shipping in Next or Stable.</p>\n<p>If a feature is not documented, they may be accompanied by an <a href=\"https://github.com/reactjs/rfcs\" rel=\"noopener noreferrer\">RFC</a>.</p>\n<p>We will post to the React blog when we‚Äôre ready to announce new experiments, but that doesn‚Äôt mean we will publicize every experiment.</p>\n<p>You can always refer to our public GitHub repository‚Äôs <a href=\"https://github.com/facebook/react/commits/master\" rel=\"noopener noreferrer\">history</a> for a comprehensive list of changes.</p>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
    Post {
        id: -1,
        unique_id: "https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html",
        link: "https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html",
        title: "Building Great User Experiences with Concurrent Mode and Suspense",
        date: 2019-11-06T00:00:00Z,
        summary: Some(
            "At React Conf 2019 we announced an experimental release of React that supports Concurrent Mode and Suspense. In this post we‚Äôll introduce best practices for using them that we‚Äôve identified through the process of building the new facebook.com.\n\nThis post will be most relevant to people working on data fetching libraries for React. \nIt shows how to best integrate them with Concurrent Mode and Suspense. The patterns introduced here are based on Relay ‚Äî our library for building data-driven UIs with GraphQL. However, the ideas in this post apply to other GraphQL clients as well as libraries using REST or other approaches.\n\nThis post is aimed at library authors. If you‚Äôre primarily an application developer, you might still find some interesting ideas here, but don‚Äôt feel like you have to read it in its entirety.\nTalk Videos \nIf you prefer to watch videos, some of the ideas from this blog post have been referenced in several React Conf 2019 presentations:\n\nData Fetching with Suspense in Relay by Joe Savona\nBuilding the New Facebook with React and Relay by Ashley Watkins\nReact Conf Keynote by Yuzhi Zheng\n\nThis post presents a deeper dive on implementing a data fetching library with Suspense.\nPutting User Experience First \nThe React team and community has long placed a deserved emphasis on developer experience: ensuring that React has good error messages, focusing on components as a way to reason locally about app behavior, crafting APIs that are predictable and encourage correct usage by design, etc. But we haven‚Äôt provided enough guidance on the best ways to achieve a great user experience in large apps.\nFor example, the React team has focused on framework performance and providing tools for developers to debug and tune application performance (e.g. React.memo). But we haven‚Äôt been as opinionated about the high-level patterns that make the difference between fast, fluid apps and slow, janky ones. We always want to ensure that React remains approachable to new users and supports a variety of use-cases ‚Äî not every app has to be ‚Äúblazing‚Äù fast. But as a community we can and should aim high. We should make it as easy as possible to build apps that start fast and stay fast, even as they grow in complexity, for users on varying devices and networks around the world. \nConcurrent Mode and Suspense are experimental features that can help developers achieve this goal. We first introduced them at JSConf Iceland in 2018, intentionally sharing details very early to give the community time to digest the new concepts and to set the stage for subsequent changes. Since then we‚Äôve completed related work, such as the new Context API and the introduction of Hooks, which are designed in part to help developers naturally write code that is more compatible with Concurrent Mode. But we didn‚Äôt want to implement these features and release them without validating that they work. So over the past year, the React, Relay, web infrastructure, and product teams at Facebook have all collaborated closely to build a new version of facebook.com that deeply integrates Concurrent Mode and Suspense to create an experience with a more fluid and app-like feel. \nThanks to this project, we‚Äôre more confident than ever that Concurrent Mode and Suspense can make it easier to deliver great, fast user experiences. But doing so requires rethinking how we approach loading code and data for our apps. Effectively all of the data-fetching on the new facebook.com is powered by Relay Hooks ‚Äî new Hooks-based Relay APIs that integrate with Concurrent Mode and Suspense out of the box.\nRelay Hooks ‚Äî and GraphQL ‚Äî won‚Äôt be for everyone, and that‚Äôs ok! Through our work on these APIs we‚Äôve identified a set of more general patterns for using Suspense. Even if Relay isn‚Äôt the right fit for you, we think the key patterns we‚Äôve introduced with Relay Hooks can be adapted to other frameworks.\nBest Practices for Suspense \nIt‚Äôs tempting to focus only on the total startup time for an app ‚Äî but it turns out that users‚Äô perception of performance is determined by more than the absolute loading time. For example, when comparing two apps with the same absolute startup time, our research shows that users will generally perceive the one with fewer intermediate loading states and fewer layout changes as having loaded faster. Suspense is a powerful tool for carefully orchestrating an elegant loading sequence with a few, well-defined states that progressively reveal content. But improving perceived performance only goes so far ‚Äî our apps still shouldn‚Äôt take forever to fetch all of their code, data, images, and other assets.\nThe traditional approach to loading data in React apps involves what we refer to as ‚Äúfetch-on-render‚Äù. First we render a component with a spinner, then fetch data on mount (componentDidMount or useEffect), and finally update to render the resulting data. It‚Äôs certainly possible to use this pattern with Suspense: instead of initially rendering a placeholder itself, a component can ‚Äúsuspend‚Äù ‚Äî indicate to React that it isn‚Äôt ready yet. This will tell React to find the nearest ancestor &lt;Suspense fallback={&lt;Placeholder/&gt;}&gt;, and render its fallback instead. If you watched earlier Suspense demos this example may feel familiar ‚Äî it‚Äôs how we originally imagined using Suspense for data-fetching. \nIt turns out that this approach has some limitations. Consider a page that shows a social media post by a user, along with comments on that post. That might be structured as a &lt;Post&gt; component that renders both the post body and a &lt;CommentList&gt; to show the comments. Using the fetch-on-render approach described above to implement this could cause sequential round trips (sometimes referred to as a ‚Äúwaterfall‚Äù). First the data for the &lt;Post&gt; component would be fetched and then the data for &lt;CommentList&gt; would be fetched, increasing the time it takes to show the full page.\nThere‚Äôs also another often-overlooked downside to this approach. If &lt;Post&gt; eagerly requires (or imports) the &lt;CommentList&gt; component, our app will have to wait to show the post body while the code for the comments is downloading. We could lazily load &lt;CommentList&gt;, but then that would delay fetching comments data and increase the time to show the full page. How do we resolve this problem without compromising on the user experience?\nRender As You Fetch \nThe fetch-on-render approach is widely used by React apps today and can certainly be used to create great apps. But can we do even better? Let‚Äôs step back and consider our goal.\nIn the above &lt;Post&gt; example, we‚Äôd ideally show the more important content ‚Äî the post body ‚Äî as early as possible, without negatively impacting the time to show the full page (including comments). Let‚Äôs consider the key constraints on any solution and look at how we can achieve them:\n\nShowing the more important content (the post body) as early as possible means that we need to load the code and data for the view incrementally. We don‚Äôt want to block showing the post body on the code for &lt;CommentList&gt; being downloaded, for example.\nAt the same time we don‚Äôt want to increase the time to show the full page including comments. So we need to start loading the code and data for the comments as soon as possible, ideally in parallel with loading the post body.\n\nThis might sound difficult to achieve ‚Äî but these constraints are actually incredibly helpful. They rule out a large number of approaches and spell out a solution for us. This brings us to the key patterns we‚Äôve implemented in Relay Hooks, and that can be adapted to other data-fetching libraries. We‚Äôll look at each one in turn and then see how they add up to achieve our goal of fast, delightful loading experiences:\n\nParallel data and view trees\nFetch in event handlers\nLoad data incrementally\nTreat code like data\n\nParallel Data and View Trees \nOne of the most appealing things about the fetch-on-render pattern is that it colocates what data a component needs with how to render that data. This colocation is great ‚Äî an example of how it makes sense to group code by concerns and not by technologies. All the issues we saw above were due to when we fetch data in this approach: upon rendering. We need to be able to fetch data before we‚Äôve rendered the component. The only way to achieve that is by extracting the data dependencies into parallel data and view trees. \nHere‚Äôs how that works in Relay Hooks. Continuing our example of a social media post with body and comments, here‚Äôs how we might define it with Relay Hooks:\n// Post.js\nfunction Post(props) {\n  // Given a reference to some post - `props.post` - *what* data\n  // do we need about that post?\n  const postData = useFragment(graphql`\n    fragment PostData on Post @refetchable(queryName: \"PostQuery\") {\n      author\n      title\n      # ...  more fields ...\n    }\n  `, props.post);\n\n  // Now that we have the data, how do we render it?\n  return (\n    &lt;div&gt;\n      &lt;h1&gt;{postData.title}&lt;/h1&gt;\n      &lt;h2&gt;by {postData.author}&lt;/h2&gt;\n      {/* more fields  */}\n    &lt;/div&gt;\n  );\n}\nAlthough the GraphQL is written within the component, Relay has a build step (Relay Compiler) that extracts these data-dependencies into separate files and aggregates the GraphQL for each view into a single query. So we get the benefit of colocating concerns, while at runtime having parallel data and view trees. Other frameworks could achieve a similar effect by allowing developers to define data-fetching logic in a sibling file (maybe Post.data.js), or perhaps integrate with a bundler to allow defining data dependencies with UI code and automatically extracting it, similar to Relay Compiler.\nThe key is that regardless of the technology we‚Äôre using to load our data ‚Äî GraphQL, REST, etc ‚Äî we can separate what data to load from how and when to actually load it. But once we do that, how and when do we fetch our data?\nFetch in Event Handlers \nImagine that we‚Äôre about to navigate from a list of a user‚Äôs posts to the page for a specific post. We‚Äôll need to download the code for that page ‚Äî Post.js ‚Äî and also fetch its data.\nWaiting until we render the component has problems as we saw above. The key is to start fetching code and data for a new view in the same event handler that triggers showing that view. We can either fetch the data within our router ‚Äî if our router supports preloading data for routes ‚Äî or in the click event on the link that triggered the navigation. It turns out that the React Router folks are already hard at work on building APIs to support preloading data for routes. But other routing frameworks can implement this idea too. \nConceptually, we want every route definition to include two things: what component to render and what data to preload, as a function of the route/url params. Here‚Äôs what such a route definition might look like. This example is loosely inspired by React Router‚Äôs route definitions and is primarily intended to demonstrate the concept, not a specific API:\n// PostRoute.js (GraphQL version)\n\n// Relay generated query for loading Post data\nimport PostQuery from \'./__generated__/PostQuery.graphql\';\n\nconst PostRoute = {\n  // a matching expression for which paths to handle\n  path: \'/post/:id\',\n\n  // what component to render for this route\n  component: React.lazy(() =&gt; import(\'./Post\')),\n\n  // data to load for this route, as function of the route\n  // parameters\n  prepare: routeParams =&gt; {\n    // Relay extracts queries from components, allowing us to reference\n    // the data dependencies -- data tree -- from outside.\n    const postData = preloadQuery(PostQuery, {\n      postId: routeParams.id,\n    });\n\n    return { postData };\n  },\n};\n\nexport default PostRoute;\nGiven such a definition, a router can:\n\nMatch a URL to a route definition.\nCall the prepare() function to start loading that route‚Äôs data. Note that prepare() is synchronous ‚Äî we don‚Äôt wait for the data to be ready, since we want to start rendering more important parts of the view (like the post body) as quickly as possible.\nPass the preloaded data to the component. If the component is ready ‚Äî the React.lazy dynamic import has completed ‚Äî the component will render and try to access its data. If not, React.lazy will suspend until the code is ready.\n\nThis approach can be generalized to other data-fetching solutions. An app that uses REST might define a route like this:\n// PostRoute.js (REST version)\n\n// Manually written logic for loading the data for the component\nimport PostData from \'./Post.data\';\n\nconst PostRoute = {\n  // a matching expression for which paths to handle\n  path: \'/post/:id\',\n\n  // what component to render for this route\n  component: React.lazy(() =&gt; import(\'./Post\')),\n\n  // data to load for this route, as function of the route\n  // parameters\n  prepare: routeParams =&gt; {\n    const postData = preloadRestEndpoint(\n      PostData.endpointUrl,\n      {\n        postId: routeParams.id,\n      },\n    );\n    return { postData };\n  },\n};\n\nexport default PostRoute;\nThis same approach can be employed not just for routing, but in other places where we show content lazily or based on user interaction. For example, a tab component could eagerly load the first tab‚Äôs code and data, and then use the same pattern as above to load the code and data for other tabs in the tab-change event handler. A component that displays a modal could preload the code and data for the modal in the click handler that triggers opening the modal, and so on. \nOnce we‚Äôve implemented the ability to start loading code and data for a view independently, we have the option to go one step further. Consider a &lt;Link to={path} /&gt; component that links to a route. If the user hovers over that link, there‚Äôs a reasonable chance they‚Äôll click it. And if they press the mouse down, there‚Äôs an even better chance that they‚Äôll complete the click. If we can load code and data for a view after the user clicks, we can also start that work before they click, getting a head start on preparing the view.\nBest of all, we can centralize that logic in a few key places ‚Äî a router or core UI components ‚Äî and get any performance benefits automatically throughout our app. Of course preloading isn‚Äôt always beneficial. It‚Äôs something an application would tune based on the user‚Äôs device or network speed to avoid eating up user‚Äôs data plans. But the pattern here makes it easier to centralize the implementation of preloading and the decision of whether to enable it or not.\nLoad Data Incrementally \nThe above patterns ‚Äî parallel data/view trees and fetching in event handlers ‚Äî let us start loading all the data for a view earlier. But we still want to be able to show more important parts of the view without waiting for all of our data. At Facebook we‚Äôve implemented support for this in GraphQL and Relay in the form of some new GraphQL directives (annotations that affect how/when data is delivered, but not what data). These new directives, called @defer and @stream, allow us to retrieve data incrementally. For example, consider our &lt;Post&gt; component from above. We want to show the body without waiting for the comments to be ready. We can achieve this with @defer and &lt;Suspense&gt;:\n// Post.js\nfunction Post(props) {\n  const postData = useFragment(graphql`\n    fragment PostData on Post {\n      author\n      title\n\n      # fetch data for the comments, but don\'t block on it being ready\n      ...CommentList @defer\n    }\n  `, props.post);\n\n  return (\n    &lt;div&gt;\n      &lt;h1&gt;{postData.title}&lt;/h1&gt;\n      &lt;h2&gt;by {postData.author}&lt;/h2&gt;\n      {/* @defer pairs naturally with &lt;Suspense&gt; to make the UI non-blocking too */}\n      &lt;Suspense fallback={&lt;Spinner/&gt;}&gt;\n        &lt;CommentList post={postData} /&gt;\n      &lt;/Suspense&gt;\n    &lt;/div&gt;\n  );\n}\nHere, our GraphQL server will stream back the results, first returning the author and title fields and then returning the comment data when it‚Äôs ready. We wrap &lt;CommentList&gt; in a &lt;Suspense&gt; boundary so that we can render the post body before &lt;CommentList&gt; and its data are ready. This same pattern can be applied to other frameworks as well. For example, apps that call a REST API might make parallel requests to fetch the body and comments data for a post to avoid blocking on all the data being ready.\nTreat Code Like Data \nBut there‚Äôs one thing that‚Äôs still missing. We‚Äôve shown how to preload data for a route ‚Äî but what about code? The example above cheated a bit and used React.lazy. However, React.lazy is, as the name implies, lazy. It won‚Äôt start downloading code until the lazy component is actually rendered ‚Äî it‚Äôs ‚Äúfetch-on-render‚Äù for code!\nTo solve this, the React team is considering APIs that would allow bundle splitting and eager preloading for code as well. That would allow a user to pass some form of lazy component to a router, and for the router to trigger loading the code alongside its data as early as possible.\nPutting It All Together \nTo recap, achieving a great loading experience means that we need to start loading code and data as early as possible, but without waiting for all of it to be ready. Parallel data and view trees allow us to load the data for a view in parallel with loading the view (code) itself. Fetching in an event handler means we can start loading data as early as possible, and even optimistically preload a view when we have enough confidence that a user will navigate to it. Loading data incrementally allows us to load important data earlier without delaying the fetching of less important data. And treating code as data ‚Äî and preloading it with similar APIs ‚Äî allows us to load it earlier too.\nUsing These Patterns \nThese patterns aren‚Äôt just ideas ‚Äî we‚Äôve implemented them in Relay Hooks and are using them in production throughout the new facebook.com (which is currently in beta testing). If you‚Äôre interested in using or learning more about these patterns, here are some resources:\n\nThe React Concurrent docs explore how to use Concurrent Mode and Suspense and go into more detail about many of these patterns. It‚Äôs a great resource to learn more about the APIs and use-cases they support.\nThe experimental release of Relay Hooks implements the patterns described here. \n\nWe‚Äôve implemented two similar example apps that demonstrate these concepts:\n\nThe Relay Hooks example app uses GitHub‚Äôs public GraphQL API to implement a simple issue tracker app. It includes nested route support with code and data preloading. The code is fully commented ‚Äî we encourage cloning the repo, running the app locally, and exploring how it works.\nWe also have a non-GraphQL version of the app that demonstrates how these concepts can be applied to other data-fetching libraries.\n\n\n\nWhile the APIs around Concurrent Mode and Suspense are still experimental, we‚Äôre confident that the ideas in this post are proven by practice. However, we understand that Relay and GraphQL aren‚Äôt the right fit for everyone. That‚Äôs ok! We‚Äôre actively exploring how to generalize these patterns to approaches such as REST, and are exploring ideas for a more generic (ie non-GraphQL) API for composing a tree of data dependencies. In the meantime, we‚Äôre excited to see what new libraries will emerge that implement the patterns described in this post to make it easier to build great, fast user experiences.",
        ),
        content: Some(
            "<p>At React Conf 2019 we announced an <a href=\"https://reactjs.org/docs/concurrent-mode-adoption.html#installation\" rel=\"noopener noreferrer\">experimental release</a> of React that supports Concurrent Mode and Suspense. In this post we‚Äôll introduce best practices for using them that we‚Äôve identified through the process of building <a href=\"https://twitter.com/facebook/status/1123322299418124289\" rel=\"noopener noreferrer\">the new facebook.com</a>.</p>\n<blockquote>\n<p>This post will be most relevant to people working on <em>data fetching libraries</em> for React. </p>\n<p>It shows how to best integrate them with Concurrent Mode and Suspense. The patterns introduced here are based on <a href=\"https://relay.dev/docs/en/experimental/step-by-step\" rel=\"noopener noreferrer\">Relay</a> ‚Äî our library for building data-driven UIs with GraphQL. However, the ideas in this post <strong>apply to other GraphQL clients as well as libraries using REST</strong> or other approaches.</p>\n</blockquote>\n<p>This post is <strong>aimed at library authors</strong>. If you‚Äôre primarily an application developer, you might still find some interesting ideas here, but don‚Äôt feel like you have to read it in its entirety.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#talk-videos\" rel=\"noopener noreferrer\"></a>Talk Videos </h2>\n<p>If you prefer to watch videos, some of the ideas from this blog post have been referenced in several React Conf 2019 presentations:</p>\n<ul>\n<li><a href=\"https://www.youtube.com/watch?v=Tl0S7QkxFE4&amp;list=PLPxbbTqCLbGHPxZpw4xj_Wwg8-fdNxJRh&amp;index=15&amp;t=0s\" rel=\"noopener noreferrer\">Data Fetching with Suspense in Relay</a> by <a href=\"https://twitter.com/en_JS\" rel=\"noopener noreferrer\">Joe Savona</a></li>\n<li><a href=\"https://www.youtube.com/watch?v=KT3XKDBZW7M&amp;list=PLPxbbTqCLbGHPxZpw4xj_Wwg8-fdNxJRh&amp;index=4\" rel=\"noopener noreferrer\">Building the New Facebook with React and Relay</a> by <a href=\"https://twitter.com/catchingash\" rel=\"noopener noreferrer\">Ashley Watkins</a></li>\n<li><a href=\"https://www.youtube.com/watch?v=uXEEL9mrkAQ&amp;list=PLPxbbTqCLbGHPxZpw4xj_Wwg8-fdNxJRh&amp;index=2\" rel=\"noopener noreferrer\">React Conf Keynote</a> by <a href=\"https://twitter.com/yuzhiz\" rel=\"noopener noreferrer\">Yuzhi Zheng</a></li>\n</ul>\n<p>This post presents a deeper dive on implementing a data fetching library with Suspense.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#putting-user-experience-first\" rel=\"noopener noreferrer\"></a>Putting User Experience First </h2>\n<p>The React team and community has long placed a deserved emphasis on developer experience: ensuring that React has good error messages, focusing on components as a way to reason locally about app behavior, crafting APIs that are predictable and encourage correct usage by design, etc. But we haven‚Äôt provided enough guidance on the best ways to achieve a great <em>user</em> experience in large apps.</p>\n<p>For example, the React team has focused on <em>framework</em> performance and providing tools for developers to debug and tune application performance (e.g. <code>React.memo</code>). But we haven‚Äôt been as opinionated about the <em>high-level patterns</em> that make the difference between fast, fluid apps and slow, janky ones. We always want to ensure that React remains approachable to new users and supports a variety of use-cases ‚Äî not every app has to be ‚Äúblazing‚Äù fast. But as a community we can and should aim high. <strong>We should make it as easy as possible to build apps that start fast and stay fast,</strong> even as they grow in complexity, for users on varying devices and networks around the world. </p>\n<p><a href=\"https://reactjs.org/docs/concurrent-mode-intro.html\" rel=\"noopener noreferrer\">Concurrent Mode</a> and <a href=\"https://reactjs.org/docs/concurrent-mode-suspense.html\" rel=\"noopener noreferrer\">Suspense</a> are experimental features that can help developers achieve this goal. We first introduced them at <a href=\"https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html\" rel=\"noopener noreferrer\">JSConf Iceland in 2018</a>, intentionally sharing details very early to give the community time to digest the new concepts and to set the stage for subsequent changes. Since then we‚Äôve completed related work, such as the new Context API and the introduction of Hooks, which are designed in part to help developers naturally write code that is more compatible with Concurrent Mode. But we didn‚Äôt want to implement these features and release them without validating that they work. So over the past year, the React, Relay, web infrastructure, and product teams at Facebook have all collaborated closely to build a new version of facebook.com that deeply integrates Concurrent Mode and Suspense to create an experience with a more fluid and app-like feel. </p>\n<p>Thanks to this project, we‚Äôre more confident than ever that Concurrent Mode and Suspense can make it easier to deliver great, <em>fast</em> user experiences. But doing so requires rethinking how we approach loading code and data for our apps. Effectively all of the data-fetching on the new facebook.com is powered by <a href=\"https://relay.dev/docs/en/experimental/step-by-step\" rel=\"noopener noreferrer\">Relay Hooks</a> ‚Äî new Hooks-based Relay APIs that integrate with Concurrent Mode and Suspense out of the box.</p>\n<p>Relay Hooks ‚Äî and GraphQL ‚Äî won‚Äôt be for everyone, and that‚Äôs ok! Through our work on these APIs we‚Äôve identified a set of more general patterns for using Suspense. <strong>Even if Relay isn‚Äôt the right fit for you, we think the key patterns we‚Äôve introduced with Relay Hooks can be adapted to other frameworks.</strong></p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#best-practices-for-suspense\" rel=\"noopener noreferrer\"></a>Best Practices for Suspense </h2>\n<p>It‚Äôs tempting to focus only on the total startup time for an app ‚Äî but it turns out that users‚Äô perception of performance is determined by more than the absolute loading time. For example, when comparing two apps with the same absolute startup time, our research shows that users will generally perceive the one with fewer intermediate loading states and fewer layout changes as having loaded faster. Suspense is a powerful tool for carefully orchestrating an elegant loading sequence with a few, well-defined states that progressively reveal content. But improving perceived performance only goes so far ‚Äî our apps still shouldn‚Äôt take forever to fetch all of their code, data, images, and other assets.</p>\n<p>The traditional approach to loading data in React apps involves what we refer to as <a href=\"https://reactjs.org/docs/concurrent-mode-suspense.html#approach-1-fetch-on-render-not-using-suspense\" rel=\"noopener noreferrer\">‚Äúfetch-on-render‚Äù</a>. First we render a component with a spinner, then fetch data on mount (<code>componentDidMount</code> or <code>useEffect</code>), and finally update to render the resulting data. It‚Äôs certainly <em>possible</em> to use this pattern with Suspense: instead of initially rendering a placeholder itself, a component can ‚Äúsuspend‚Äù ‚Äî indicate to React that it isn‚Äôt ready yet. This will tell React to find the nearest ancestor <code>&lt;Suspense fallback={&lt;Placeholder/&gt;}&gt;</code>, and render its fallback instead. If you watched earlier Suspense demos this example may feel familiar ‚Äî it‚Äôs how we originally imagined using Suspense for data-fetching. </p>\n<p>It turns out that this approach has some limitations. Consider a page that shows a social media post by a user, along with comments on that post. That might be structured as a <code>&lt;Post&gt;</code> component that renders both the post body and a <code>&lt;CommentList&gt;</code> to show the comments. Using the fetch-on-render approach described above to implement this could cause sequential round trips (sometimes referred to as a ‚Äúwaterfall‚Äù). First the data for the <code>&lt;Post&gt;</code> component would be fetched and then the data for <code>&lt;CommentList&gt;</code> would be fetched, increasing the time it takes to show the full page.</p>\n<p>There‚Äôs also another often-overlooked downside to this approach. If <code>&lt;Post&gt;</code> eagerly requires (or imports) the <code>&lt;CommentList&gt;</code> component, our app will have to wait to show the post <em>body</em> while the code for the <em>comments</em> is downloading. We could lazily load <code>&lt;CommentList&gt;</code>, but then that would delay fetching comments data and increase the time to show the full page. How do we resolve this problem without compromising on the user experience?</p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#render-as-you-fetch\" rel=\"noopener noreferrer\"></a>Render As You Fetch </h2>\n<p>The fetch-on-render approach is widely used by React apps today and can certainly be used to create great apps. But can we do even better? Let‚Äôs step back and consider our goal.</p>\n<p>In the above <code>&lt;Post&gt;</code> example, we‚Äôd ideally show the more important content ‚Äî the post body ‚Äî as early as possible, <em>without</em> negatively impacting the time to show the full page (including comments). Let‚Äôs consider the key constraints on any solution and look at how we can achieve them:</p>\n<ul>\n<li>Showing the more important content (the post body) as early as possible means that we need to load the code and data for the view incrementally. We <em>don‚Äôt want to block showing the post body</em> on the code for <code>&lt;CommentList&gt;</code> being downloaded, for example.</li>\n<li>At the same time we don‚Äôt want to increase the time to show the full page including comments. So we need to <em>start loading the code and data for the comments</em> as soon as possible, ideally <em>in parallel</em> with loading the post body.</li>\n</ul>\n<p>This might sound difficult to achieve ‚Äî but these constraints are actually incredibly helpful. They rule out a large number of approaches and spell out a solution for us. This brings us to the key patterns we‚Äôve implemented in Relay Hooks, and that can be adapted to other data-fetching libraries. We‚Äôll look at each one in turn and then see how they add up to achieve our goal of fast, delightful loading experiences:</p>\n<ol>\n<li>Parallel data and view trees</li>\n<li>Fetch in event handlers</li>\n<li>Load data incrementally</li>\n<li>Treat code like data</li>\n</ol>\n<h3><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#parallel-data-and-view-trees\" rel=\"noopener noreferrer\"></a>Parallel Data and View Trees </h3>\n<p>One of the most appealing things about the fetch-on-render pattern is that it colocates <em>what</em> data a component needs with <em>how</em> to render that data. This colocation is great ‚Äî an example of how it makes sense to group code by concerns and not by technologies. All the issues we saw above were due to <em>when</em> we fetch data in this approach: upon rendering. We need to be able to fetch data <em>before</em> we‚Äôve rendered the component. The only way to achieve that is by extracting the data dependencies into parallel data and view trees. </p>\n<p>Here‚Äôs how that works in Relay Hooks. Continuing our example of a social media post with body and comments, here‚Äôs how we might define it with Relay Hooks:</p>\n<div><pre><code><span>// Post.js</span>\n<span>function</span> <span>Post</span><span>(</span>props<span>)</span> <span>{</span>\n  <span>// Given a reference to some post - `props.post` - *what* data</span>\n  <span>// do we need about that post?</span>\n  <span>const</span> postData <span>=</span> <span>useFragment</span><span>(</span>graphql<span><span>`\n    fragment PostData on Post @refetchable(queryName: \"PostQuery\") {\n      author\n      title\n      # ...  more fields ...\n    }\n  `</span></span><span>,</span> props<span>.</span>post<span>)</span><span>;</span>\n\n  <span>// Now that we have the data, how do we render it?</span>\n  <span>return</span> <span>(</span>\n    <span><span><span>&lt;</span>div</span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>h1</span><span>&gt;</span></span><span>{</span>postData<span>.</span>title<span>}</span><span><span><span>&lt;/</span>h1</span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>h2</span><span>&gt;</span></span><span>by </span><span>{</span>postData<span>.</span>author<span>}</span><span><span><span>&lt;/</span>h2</span><span>&gt;</span></span><span>\n      </span><span>{</span><span>/* more fields  */</span><span>}</span><span>\n    </span><span><span><span>&lt;/</span>div</span><span>&gt;</span></span>\n  <span>)</span><span>;</span>\n<span>}</span></code></pre></div>\n<p>Although the GraphQL is written within the component, Relay has a build step (Relay Compiler) that extracts these data-dependencies into separate files and aggregates the GraphQL for each view into a single query. So we get the benefit of colocating concerns, while at runtime having parallel data and view trees. Other frameworks could achieve a similar effect by allowing developers to define data-fetching logic in a sibling file (maybe <code>Post.data.js</code>), or perhaps integrate with a bundler to allow defining data dependencies with UI code and automatically extracting it, similar to Relay Compiler.</p>\n<p>The key is that regardless of the technology we‚Äôre using to load our data ‚Äî GraphQL, REST, etc ‚Äî we can separate <em>what</em> data to load from how and when to actually load it. But once we do that, how and when <em>do</em> we fetch our data?</p>\n<h3><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#fetch-in-event-handlers\" rel=\"noopener noreferrer\"></a>Fetch in Event Handlers </h3>\n<p>Imagine that we‚Äôre about to navigate from a list of a user‚Äôs posts to the page for a specific post. We‚Äôll need to download the code for that page ‚Äî <code>Post.js</code> ‚Äî and also fetch its data.</p>\n<p>Waiting until we render the component has problems as we saw above. The key is to start fetching code and data for a new view <em>in the same event handler that triggers showing that view</em>. We can either fetch the data within our router ‚Äî if our router supports preloading data for routes ‚Äî or in the click event on the link that triggered the navigation. It turns out that the React Router folks are already hard at work on building APIs to support preloading data for routes. But other routing frameworks can implement this idea too. </p>\n<p>Conceptually, we want every route definition to include two things: what component to render and what data to preload, as a function of the route/url params. Here‚Äôs what such a route definition <em>might</em> look like. This example is loosely inspired by React Router‚Äôs route definitions and is <em>primarily intended to demonstrate the concept, not a specific API</em>:</p>\n<div><pre><code><span>// PostRoute.js (GraphQL version)</span>\n\n<span>// Relay generated query for loading Post data</span>\n<span>import</span> PostQuery <span>from</span> <span>\'./__generated__/PostQuery.graphql\'</span><span>;</span>\n\n<span>const</span> PostRoute <span>=</span> <span>{</span>\n  <span>// a matching expression for which paths to handle</span>\n  path<span>:</span> <span>\'/post/:id\'</span><span>,</span>\n\n  <span>// what component to render for this route</span>\n  component<span>:</span> React<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>import</span><span>(</span><span>\'./Post\'</span><span>)</span><span>)</span><span>,</span>\n\n  <span>// data to load for this route, as function of the route</span>\n  <span>// parameters</span>\n  prepare<span>:</span> routeParams <span>=&gt;</span> <span>{</span>\n    <span>// Relay extracts queries from components, allowing us to reference</span>\n    <span>// the data dependencies -- data tree -- from outside.</span>\n    <span>const</span> postData <span>=</span> <span>preloadQuery</span><span>(</span>PostQuery<span>,</span> <span>{</span>\n      postId<span>:</span> routeParams<span>.</span>id<span>,</span>\n    <span>}</span><span>)</span><span>;</span>\n\n    <span>return</span> <span>{</span> postData <span>}</span><span>;</span>\n  <span>}</span><span>,</span>\n<span>}</span><span>;</span>\n\n<span>export</span> <span>default</span> PostRoute<span>;</span></code></pre></div>\n<p>Given such a definition, a router can:</p>\n<ul>\n<li>Match a URL to a route definition.</li>\n<li>Call the <code>prepare()</code> function to start loading that route‚Äôs data. Note that <code>prepare()</code> is synchronous ‚Äî <em>we don‚Äôt wait for the data to be ready</em>, since we want to start rendering more important parts of the view (like the post body) as quickly as possible.</li>\n<li>Pass the preloaded data to the component. If the component is ready ‚Äî the <code>React.lazy</code> dynamic import has completed ‚Äî the component will render and try to access its data. If not, <code>React.lazy</code> will suspend until the code is ready.</li>\n</ul>\n<p>This approach can be generalized to other data-fetching solutions. An app that uses REST might define a route like this:</p>\n<div><pre><code><span>// PostRoute.js (REST version)</span>\n\n<span>// Manually written logic for loading the data for the component</span>\n<span>import</span> PostData <span>from</span> <span>\'./Post.data\'</span><span>;</span>\n\n<span>const</span> PostRoute <span>=</span> <span>{</span>\n  <span>// a matching expression for which paths to handle</span>\n  path<span>:</span> <span>\'/post/:id\'</span><span>,</span>\n\n  <span>// what component to render for this route</span>\n  component<span>:</span> React<span>.</span><span>lazy</span><span>(</span><span>(</span><span>)</span> <span>=&gt;</span> <span>import</span><span>(</span><span>\'./Post\'</span><span>)</span><span>)</span><span>,</span>\n\n  <span>// data to load for this route, as function of the route</span>\n  <span>// parameters</span>\n  prepare<span>:</span> routeParams <span>=&gt;</span> <span>{</span>\n    <span>const</span> postData <span>=</span> <span>preloadRestEndpoint</span><span>(</span>\n      PostData<span>.</span>endpointUrl<span>,</span>\n      <span>{</span>\n        postId<span>:</span> routeParams<span>.</span>id<span>,</span>\n      <span>}</span><span>,</span>\n    <span>)</span><span>;</span>\n    <span>return</span> <span>{</span> postData <span>}</span><span>;</span>\n  <span>}</span><span>,</span>\n<span>}</span><span>;</span>\n\n<span>export</span> <span>default</span> PostRoute<span>;</span></code></pre></div>\n<p>This same approach can be employed not just for routing, but in other places where we show content lazily or based on user interaction. For example, a tab component could eagerly load the first tab‚Äôs code and data, and then use the same pattern as above to load the code and data for other tabs in the tab-change event handler. A component that displays a modal could preload the code and data for the modal in the click handler that triggers opening the modal, and so on. </p>\n<p>Once we‚Äôve implemented the ability to start loading code and data for a view independently, we have the option to go one step further. Consider a <code>&lt;Link to={path} /&gt;</code> component that links to a route. If the user hovers over that link, there‚Äôs a reasonable chance they‚Äôll click it. And if they press the mouse down, there‚Äôs an even better chance that they‚Äôll complete the click. If we can load code and data for a view <em>after</em> the user clicks, we can also start that work <em>before</em> they click, getting a head start on preparing the view.</p>\n<p>Best of all, we can centralize that logic in a few key places ‚Äî a router or core UI components ‚Äî and get any performance benefits automatically throughout our app. Of course preloading isn‚Äôt always beneficial. It‚Äôs something an application would tune based on the user‚Äôs device or network speed to avoid eating up user‚Äôs data plans. But the pattern here makes it easier to centralize the implementation of preloading and the decision of whether to enable it or not.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#load-data-incrementally\" rel=\"noopener noreferrer\"></a>Load Data Incrementally </h3>\n<p>The above patterns ‚Äî parallel data/view trees and fetching in event handlers ‚Äî let us start loading all the data for a view earlier. But we still want to be able to show more important parts of the view without waiting for <em>all</em> of our data. At Facebook we‚Äôve implemented support for this in GraphQL and Relay in the form of some new GraphQL directives (annotations that affect how/when data is delivered, but not what data). These new directives, called <code>@defer</code> and <code>@stream</code>, allow us to retrieve data incrementally. For example, consider our <code>&lt;Post&gt;</code> component from above. We want to show the body without waiting for the comments to be ready. We can achieve this with <code>@defer</code> and <code>&lt;Suspense&gt;</code>:</p>\n<div><pre><code><span>// Post.js</span>\n<span>function</span> <span>Post</span><span>(</span>props<span>)</span> <span>{</span>\n  <span>const</span> postData <span>=</span> <span>useFragment</span><span>(</span>graphql<span><span>`\n    fragment PostData on Post {\n      author\n      title\n\n      # fetch data for the comments, but don\'t block on it being ready\n      ...CommentList @defer\n    }\n  `</span></span><span>,</span> props<span>.</span>post<span>)</span><span>;</span>\n\n  <span>return</span> <span>(</span>\n    <span><span><span>&lt;</span>div</span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>h1</span><span>&gt;</span></span><span>{</span>postData<span>.</span>title<span>}</span><span><span><span>&lt;/</span>h1</span><span>&gt;</span></span><span>\n      </span><span><span><span>&lt;</span>h2</span><span>&gt;</span></span><span>by </span><span>{</span>postData<span>.</span>author<span>}</span><span><span><span>&lt;/</span>h2</span><span>&gt;</span></span><span>\n      </span><span>{</span><span>/* @defer pairs naturally with &lt;Suspense&gt; to make the UI non-blocking too */</span><span>}</span><span>\n      </span><span><span><span>&lt;</span>Suspense</span> <span>fallback</span><span><span>=</span><span>{</span><span><span><span>&lt;</span>Spinner</span><span>/&gt;</span></span><span>}</span></span><span>&gt;</span></span><span>\n        </span><span><span><span>&lt;</span>CommentList</span> <span>post</span><span><span>=</span><span>{</span>postData<span>}</span></span> <span>/&gt;</span></span><span>\n      </span><span><span><span>&lt;/</span>Suspense</span><span>&gt;</span></span><span>\n    </span><span><span><span>&lt;/</span>div</span><span>&gt;</span></span>\n  <span>)</span><span>;</span>\n<span>}</span></code></pre></div>\n<p>Here, our GraphQL server will stream back the results, first returning the <code>author</code> and <code>title</code> fields and then returning the comment data when it‚Äôs ready. We wrap <code>&lt;CommentList&gt;</code> in a <code>&lt;Suspense&gt;</code> boundary so that we can render the post body before <code>&lt;CommentList&gt;</code> and its data are ready. This same pattern can be applied to other frameworks as well. For example, apps that call a REST API might make parallel requests to fetch the body and comments data for a post to avoid blocking on all the data being ready.</p>\n<h3><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#treat-code-like-data\" rel=\"noopener noreferrer\"></a>Treat Code Like Data </h3>\n<p>But there‚Äôs one thing that‚Äôs still missing. We‚Äôve shown how to preload <em>data</em> for a route ‚Äî but what about code? The example above cheated a bit and used <code>React.lazy</code>. However, <code>React.lazy</code> is, as the name implies, <em>lazy</em>. It won‚Äôt start downloading code until the lazy component is actually rendered ‚Äî it‚Äôs ‚Äúfetch-on-render‚Äù for code!</p>\n<p>To solve this, the React team is considering APIs that would allow bundle splitting and eager preloading for code as well. That would allow a user to pass some form of lazy component to a router, and for the router to trigger loading the code alongside its data as early as possible.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#putting-it-all-together\" rel=\"noopener noreferrer\"></a>Putting It All Together </h2>\n<p>To recap, achieving a great loading experience means that we need to <strong>start loading code and data as early as possible, but without waiting for all of it to be ready</strong>. Parallel data and view trees allow us to load the data for a view in parallel with loading the view (code) itself. Fetching in an event handler means we can start loading data as early as possible, and even optimistically preload a view when we have enough confidence that a user will navigate to it. Loading data incrementally allows us to load important data earlier without delaying the fetching of less important data. And treating code as data ‚Äî and preloading it with similar APIs ‚Äî allows us to load it earlier too.</p>\n<h2><a href=\"https://reactjs.org/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html#using-these-patterns\" rel=\"noopener noreferrer\"></a>Using These Patterns </h2>\n<p>These patterns aren‚Äôt just ideas ‚Äî we‚Äôve implemented them in Relay Hooks and are using them in production throughout the new facebook.com (which is currently in beta testing). If you‚Äôre interested in using or learning more about these patterns, here are some resources:</p>\n<ul>\n<li>The <a href=\"https://reactjs.org/docs/concurrent-mode-intro.html\" rel=\"noopener noreferrer\">React Concurrent docs</a> explore how to use Concurrent Mode and Suspense and go into more detail about many of these patterns. It‚Äôs a great resource to learn more about the APIs and use-cases they support.</li>\n<li>The <a href=\"https://relay.dev/docs/en/experimental/step-by-step\" rel=\"noopener noreferrer\">experimental release of Relay Hooks</a> implements the patterns described here. </li>\n<li>\n<p>We‚Äôve implemented two similar example apps that demonstrate these concepts:</p>\n<ul>\n<li>The <a href=\"https://github.com/relayjs/relay-examples/tree/master/issue-tracker\" rel=\"noopener noreferrer\">Relay Hooks example app</a> uses GitHub‚Äôs public GraphQL API to implement a simple issue tracker app. It includes nested route support with code and data preloading. The code is fully commented ‚Äî we encourage cloning the repo, running the app locally, and exploring how it works.</li>\n<li>We also have a <a href=\"https://github.com/gaearon/suspense-experimental-github-demo\" rel=\"noopener noreferrer\">non-GraphQL version of the app</a> that demonstrates how these concepts can be applied to other data-fetching libraries.</li>\n</ul>\n</li>\n</ul>\n<p>While the APIs around Concurrent Mode and Suspense are <a href=\"https://reactjs.org/docs/concurrent-mode-adoption.html#who-is-this-experimental-release-for\" rel=\"noopener noreferrer\">still experimental</a>, we‚Äôre confident that the ideas in this post are proven by practice. However, we understand that Relay and GraphQL aren‚Äôt the right fit for everyone. That‚Äôs ok! <strong>We‚Äôre actively exploring how to generalize these patterns to approaches such as REST,</strong> and are exploring ideas for a more generic (ie non-GraphQL) API for composing a tree of data dependencies. In the meantime, we‚Äôre excited to see what new libraries will emerge that implement the patterns described in this post to make it easier to build great, <em>fast</em> user experiences.</p>",
        ),
        media_type: None,
        media_link: None,
        comments_link: None,
    },
]
