-
Notifications
You must be signed in to change notification settings - Fork 7.9k
React 18 RC - Upgrade Guide #4384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
e3ae2d1
Blog Draft: React 18 RC Upgrade Guide
rickhanlonii fb51e55
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii 9712296
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii 56f7ed3
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii 84890dc
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii ede8f3b
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii 16a4e93
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii d956a5b
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii e11ab88
Minor updates
rickhanlonii 205dc58
Update content/blog/2022-02-25-react-v18-rc.md
rickhanlonii b44606b
Update Strict Effect section
rickhanlonii 2b78641
Fill in testing section
acdlite a423528
Minor updates
rickhanlonii b5f8669
Update react-dom imports
acdlite 86327a9
Add link to react-testing-library
acdlite 95cd07a
Remove Suspense specifics
rickhanlonii 5bffadc
Update to react-dom/client
rickhanlonii 239661b
Updates to SSR
rickhanlonii bfcc7bd
Minor updates
rickhanlonii bcc3946
Fix typo
rickhanlonii 96e4394
Minor updates to wording
rickhanlonii b515297
Minor updates to wording
rickhanlonii 91af724
Tweak call to action
acdlite File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -320,4 +320,4 @@ export default function Bio() { | |
|
|
||
| </Solution> | ||
|
|
||
| </Challenges> | ||
| </Challenges> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,253 @@ | ||
| --- | ||
| title: "React v18.0 Release Candidate: Upgrade Guide" | ||
| author: [rickhanlonii] | ||
| --- | ||
|
|
||
| Today we’re publishing the second release candidate for React 18. With this release, we’re encouraging users to install and test React 18 to [raise any issues](https://github.com/facebook/react/issues/new/choose) for any problems you encounter in the upgrade before we publish the full stable release. | ||
|
|
||
| As we shared at [React Conf](https://reactjs.org/blog/2021/12/17/react-conf-2021-recap.html), React 18 will include our new concurrent renderer and a gradual migration strategy for concurrent features. React 18 also includes a small number of breaking changes and features outside of concurrent rendering. In this post we will describe the changes to expect when upgrading to React 18. | ||
|
|
||
| *Note for React Native users: React 18 will ship in React Native with the New React Native Architecture. For more information, see the [React Conf keynote here](https://www.youtube.com/watch?v=FZ0cG47msEk&t=1530s).* | ||
|
|
||
| ## Installing | ||
|
|
||
| To install the latest React 18 RC, use the `@rc` tag: | ||
|
|
||
| ```bash | ||
| npm install react@rc react-dom@rc | ||
| ``` | ||
|
|
||
| Or if you’re using yarn: | ||
|
|
||
| ```bash | ||
| yarn add react@rc react-dom@rc | ||
| ``` | ||
|
|
||
| ## New Client Root APIs | ||
|
|
||
| When you first install React 18, you will see a warning in the console: | ||
|
|
||
|  | ||
|
|
||
| React 18 introduces a new root API which provides better ergonomics for managing roots. The new root API also enables the new concurrent renderer, which allows you to opt-into concurrent features. | ||
|
|
||
| ```js | ||
| // Before | ||
| import { render } from 'react-dom'; | ||
| const container = document.getElementById('app'); | ||
| render(<App tab="home" />, container); | ||
|
|
||
| // After | ||
| import { createRoot } from 'react-dom/client'; | ||
| const container = document.getElementById('app'); | ||
| const root = createRoot(container); | ||
| root.render(<App tab="home" />); | ||
|
|
||
| ``` | ||
|
|
||
| We’ve also changed `unmountComponentAtNode` to `root.unmount`: | ||
|
|
||
| ```js | ||
| // Before | ||
| unmountComponentAtNode(containter); | ||
|
rickhanlonii marked this conversation as resolved.
Outdated
|
||
|
|
||
| // After | ||
| root.unmount(); | ||
| ``` | ||
|
|
||
| And removed the callback from `render`: | ||
|
|
||
| ```js | ||
| // Before | ||
| import { render } from 'react-dom'; | ||
| const container = document.getElementById('app'); | ||
| render(<App tab="home" />, container, () => { | ||
| console.log('rendered'); | ||
| }); | ||
|
|
||
| // After | ||
| function AppWithCallbackAfterRender() { | ||
| useEffect(() => { | ||
| console.log('rendered'); | ||
| }); | ||
|
|
||
| return <App tab="home" /> | ||
| } | ||
|
|
||
| import { createRoot } from 'react-dom/client'; | ||
| const container = document.getElementById('app'); | ||
| const root = createRoot(container); | ||
| root.render(<AppWithCallbackAfterRender />); | ||
|
rickhanlonii marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| Finally, if your app uses server-side rendering with hydration, upgrade `hydrate` to `hydrateRoot`: | ||
|
|
||
| ```js | ||
| // Before | ||
| import { hydrate } from 'react-dom'; | ||
| const container = document.getElementById('app'); | ||
| hydrate(<App tab="home" />, container); | ||
|
|
||
| // After | ||
| import { hydrateRoot } from 'react-dom/client'; | ||
| const container = document.getElementById('app'); | ||
| const root = hydrateRoot(container, <App tab="home" />); | ||
| // Unlike with createRoot, you don't need a separate root.render() call here. | ||
| ``` | ||
|
|
||
| For more information, see the [working group discussion here](https://github.com/reactwg/react-18/discussions/5). | ||
|
|
||
| ## Updates to Server Rendering APIs | ||
|
|
||
| In this release, we’re revamping our server rendering APIs to support Suspense on the server and Streaming SSR. | ||
|
|
||
| As part of these changes, the following APIs will continue working, but with limited support for Suspense. Instead of erroring, these APIs will server render the nearest fallback for any subtree that suspends, and retry rendering on the client: | ||
|
|
||
| * `renderToString` | ||
| * `renderToStaticMarkup` | ||
|
rickhanlonii marked this conversation as resolved.
Outdated
|
||
|
|
||
| For full support of Suspense on the server, React 18 introduces new recommended streaming APIs. These APIs will retry suspended Suspense boundaries on the server, streaming the server-rendered content to the client when it is available: | ||
|
|
||
| * `renderToPipeableStream` | ||
| * `renderToReadableStream` | ||
|
|
||
| These new streaming APIs replace the old streaming APIs, which are now deprecated and will warn: | ||
|
|
||
| * `renderToNodeStream` | ||
| * `renderToStaticNodeStream` | ||
|
|
||
| For more information on the changes to these APIs, see the working group post on [Upgrading to React 18 on the server](https://github.com/reactwg/react-18/discussions/22), a [deep dive on the new Suspense SSR Architecture](https://github.com/reactwg/react-18/discussions/37), and [Shaundai Person’s](https://twitter.com/shaundai) talk on [Streaming Server Rendering with Suspense](https://www.youtube.com/watch?v=pj5N-Khihgc) at React Conf 2021. | ||
|
|
||
| ## Automatic Batching | ||
|
|
||
| React 18 adds out-of-the-box performance improvements by doing more batching by default. Batching is when React groups multiple state updates into a single re-render for better performance. Before React 18, we only batched updates inside React event handlers. Updates inside of promises, setTimeout, native event handlers, or any other event were not batched in React by default: | ||
|
|
||
| ```js | ||
| // Before React 18 only React events were batched | ||
|
|
||
| function handleClick() { | ||
| setCount(c => c + 1); | ||
| setFlag(f => !f); | ||
| // React will only re-render once at the end (that's batching!) | ||
| } | ||
|
|
||
| setTimeout(() => { | ||
| setCount(c => c + 1); | ||
| setFlag(f => !f); | ||
| // React will render twice, once for each state update (no batching) | ||
| }, 1000); | ||
| ``` | ||
|
|
||
|
|
||
| Starting in React 18 with `createRoot`, all updates will be automatically batched, no matter where they originate from. This means that updates inside of timeouts, promises, native event handlers or any other event will batch the same way as updates inside of React events: | ||
|
|
||
| ```js | ||
| // After React 18 updates inside of timeouts, promises, | ||
| // native event handlers or any other event are batched. | ||
|
|
||
| function handleClick() { | ||
| setCount(c => c + 1); | ||
| setFlag(f => !f); | ||
| // React will only re-render once at the end (that's batching!) | ||
| } | ||
|
|
||
| setTimeout(() => { | ||
| setCount(c => c + 1); | ||
| setFlag(f => !f); | ||
| // React will only re-render once at the end (that's batching!) | ||
| }, 1000); | ||
| ``` | ||
|
|
||
| This is a breaking change, but we expect this to result in less work rendering, and therefore better performance in your applications. To opt-out of automatic batching, you can use `flushSync`: | ||
|
|
||
| ```js | ||
| import { flushSync } from 'react-dom'; | ||
|
|
||
| function handleClick() { | ||
| flushSync(() => { | ||
| setCounter(c => c + 1); | ||
| }); | ||
| // React has updated the DOM by now | ||
| flushSync(() => { | ||
| setFlag(f => !f); | ||
| }); | ||
| // React has updated the DOM by now | ||
| } | ||
| ``` | ||
|
|
||
| For more information, see the [Automatic batching deep dive](https://github.com/reactwg/react-18/discussions/21). | ||
|
|
||
| ## New APIs for Libraries | ||
|
|
||
| In the React 18 Working Group we worked with library maintainers to create new APIs needed to support concurrent rendering for use cases specific to their use case in areas like styles, external stores, and accessibility. To support React 18, some libraries may need to switch to one of the following APIs: | ||
|
|
||
| * `useId` is a new hook for generating unique IDs on both the client and server, while avoiding hydration mismatches. This solves an issue that already exists in React 17 and below, but it's even more important in React 18 because of how our streaming server renderer delivers HTML out-of-order. For more information see the [useId post in the working group](https://github.com/reactwg/react-18/discussions/111). | ||
| * `useSyncExternalStore` is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. This new API is recommended for any library that integrates with state external to React. For more information, see the [useSyncExternalStore overview post](https://github.com/reactwg/react-18/discussions/70) and [useSyncExternalStore API details](https://github.com/reactwg/react-18/discussions/86). | ||
| * `useInsertionEffect` is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. This hook will run after the DOM is mutated, but before layout effects read the new layout. This solves an issue that already exists in React 17 and below, but is even more important in React 18 because React yields to the browser during concurrent rendering, giving it a chance to recalculate layout. For more information, see the [Library Upgrade Guide for `<style>`](https://github.com/reactwg/react-18/discussions/110). | ||
|
|
||
| React 18 also introduces new APIs for concurrent rendering such as `startTransition` and `useDeferredValue`, which we will share more about in the upcoming stable release post. | ||
|
|
||
| ## Updates to Strict Mode | ||
|
|
||
| In the future, we'd like to add a feature to React which would allow a component that unmounts to remount and restore the previous component state. This will give React better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times in a component using the same state. | ||
|
|
||
| To help surface these issues, React 18 introduces a new feature to Strict Mode. This new feature will automatically unmount and remount every component in development, whenever a component mounts, restoring the previous state on the second mount. | ||
|
|
||
| Before this change, React would mount the component and create the effects: | ||
|
|
||
| ``` | ||
| * React mounts the component. | ||
| * Layout effects are created. | ||
| * Effect effects are created. | ||
| ``` | ||
|
|
||
| With Strict Mode in React 18, React will simulate unmounting and remounting the component: | ||
|
|
||
| ``` | ||
| * React mounts the component. | ||
| * Layout effects are created. | ||
| * Effect effects are created. | ||
| * React simulates unmounting the component. | ||
| * Layout effects are destroyed. | ||
| * Effects are destroyed. | ||
| * React simulates mounting the component with the previous state. | ||
| * Layout effect setup code runs | ||
| * Effect setup code runs | ||
| ``` | ||
|
|
||
| For more information, see the Working Group posts for [Adding Strict Effects to Strict Mode](https://github.com/reactwg/react-18/discussions/19) and [How to Support Strict Effects](https://github.com/reactwg/react-18/discussions/18). | ||
|
|
||
| ## Configuring Your Testing Environment | ||
|
|
||
| When you first update your tests to use `createRoot`, you may see this warning in your test console: | ||
|
|
||
| > The current testing environment is not configured to support act(...) | ||
|
|
||
| To fix this, set `global.IS_REACT_ACT_ENVIRONMENT` to `true` before running your test: | ||
|
|
||
| ```js | ||
| // In your test setup file | ||
| global.IS_REACT_ACT_ENVIRONMENT = true; | ||
| ``` | ||
|
|
||
| The purpose of the flag is to tell React that it's running in a unit test-like environment. React will log helpful warnings if you forget to wrap an update with `act`. | ||
|
|
||
| You can also set the flag to `false` to tell React that `act` isn't needed. This can be useful for end-to-end tests that simulate a full browser environment. | ||
|
|
||
| Eventually, we expect testing libraries will configure this for you automatically. For example, the [next version of React Testing Library has built-in support for React 18](https://github.com/testing-library/react-testing-library/issues/509#issuecomment-917989936) without any additional configuration. | ||
|
|
||
| [More background on the the `act` testing API and related changes](https://github.com/reactwg/react-18/discussions/102) is available in the working group. | ||
|
|
||
| ## Dropping Support for Internet Explorer | ||
|
|
||
| In this release, React is dropping support for Internet Explorer, which is [going out of support on June 15, 2022](https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge). We’re making this change now because new features introduced in React 18 are built using modern browser features such as microtasks which cannot be adequately polyfilled in IE. | ||
|
|
||
| If you need to support Internet Explorer we recommend you stay with React 17. | ||
|
|
||
| ## Other Changes | ||
|
|
||
| * [Update to remove the "setState on unmounted component" warning](https://github.com/reactwg/react-18/discussions/82) | ||
| * [Suspense no longer requires a `fallback` prop to capture](https://github.com/reactwg/react-18/discussions/72) | ||
| * [Components can now render undefined](https://github.com/reactwg/react-18/discussions/75) | ||
| * [Deprecated renderSubtreeIntoContainer](https://github.com/facebook/react/pull/23355) | ||
| * [StrictMode updated to not silence double logging by default](https://github.com/reactwg/react-18/discussions/96) | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.