How to update react
How to update react
Customize Theme
Updating to Newer React Versions
Cool new features and under-the-hood improvements get added to to React all the time. If your apps rely on React, you will find yourself at some point needing to update your version of React to something more recent to take advantage of these changes. This article will quickly run through how you can jump between versions of React on an existing app really painlessly.
When Using Directly via a CDN
Like we covered in Building Your First React App, the easiest (and preferred) way to get started with React is by referencing the React and ReactDOM libraries directly from a CDN and specifying them in your HTML page like you would any old script:
The version of React that is used can easily be inferred by looking at the path. This one is clearly version 16. To change the version to something else, I don’t recommend randomly putting version numbers in the path and seeing whether they return a valid JS file or not. Instead, there is a better way.
Once you have picked the version, you will typically see a lot of files that you can use. Choose the development.js file equivalent for both React (react.development.js) and ReactDOM (react-dom.development.js). For example, here is the path for referencing version 16.7.0:
Whatever you do, you should ensure that the version number for both React and ReactDOM are the same. If you mix and match versions between them, you might run into some weird issues.
When Using Create React App
Once you have gotten yourself familiar with React, the other popular way to use React as part of your app is via the popular Create React App command tool. The Setting Up Your React Dev Environment Easily article goes into more detail how you can use it, but overall it is so simple, there is no harm in repeating it here.
In your terminal or command line, enter the following commands to create a new app using called my-cool-app:
After a few moments, you will see a new React app running in your browser:
You can look at the my-cool-app folder to see all the files and folders that now make up your React project:
Now, figuring out the version of React used by Create React App requires some slight digging. In the root of your project folder, open package.json. One of the entries you see will be for react and react-dom:
Notice the version number associated with them. In our example, the version specified for React and ReactDOM is 16.7.0. To change to a different version, you’ll need to the visit the NPM page for both React and ReactDOM to see what versions you have available to use:
Copy the version value you are looking for and enter it in your JSON file for both the react and react-dom entries. For example, if I want to go back in time to React 15.6.0, I can modify my package.json entries as follows:
Once you have updated package.json and saved the change, you aren’t done. You need to go back to your Terminal or Command Prompt and run npm update at the root of your project folder to ensure the new changes get picked up:
Once the update step has finished, you can continue working on your project and testing your app like you normally would.
Lastly, when specifying the version in package.json, you can use modifiers like the tilde (
) and carat (^) in front of the version number. These characters allow you to specify what default behavior you will see when a newer package is available than the one you are referencing. This is a fairly complex topic, so I encourage you to read the official NPM guidance at this location.
Conclusion
Whether you move over to a newer (or older) version of React depends entirely on what you are looking for. Every change like this will incur a cost where you will need to re-test your app’s functionality to ensure nothing has broken. For the most part, the changes made to React with each release (either major or minor) is worth the added cost and hassle. Besides giving you new APIs, you get bug fixes, performance improvements, and just general goodness that you will indirectly benefit from by moving to the latest (supported) version of React you can get your hands on!
How to Upgrade to React 18
As we shared in the release post, React 18 introduces features powered by our new concurrent renderer, with a gradual adoption strategy for existing applications. In this post, we will guide you through the steps for upgrading to React 18.
Please report any issues you encounter while upgrading to React 18.
Note for React Native users: React 18 will ship in a future version of React Native. This is because React 18 relies on the New React Native Architecture to benefit from the new capabilities presented in this blogpost. For more information, see the React Conf keynote here.
To install the latest version of React:
Or if you’re using yarn:
Updates to Client Rendering APIs
When you first install React 18, you will see a warning in the console:
ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it’s running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
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.
We’ve also changed unmountComponentAtNode to root.unmount :
We’ve also removed the callback from render, since it usually does not have the expected result when using Suspense:
There is no one-to-one replacement for the old render callback API — it depends on your use case. See the working group post for Replacing render with createRoot for more information.
Finally, if your app uses server-side rendering with hydration, upgrade hydrate to hydrateRoot :
Updates to Server Rendering APIs
In this release, we’re revamping our react-dom/server APIs to fully support Suspense on the server and Streaming SSR. As part of these changes, we’re deprecating the old Node streaming API, which does not support incremental Suspense streaming on the server.
Using this API will now warn:
Instead, for streaming in Node environments, use:
We’re also introducing a new API to support streaming SSR with Suspense for modern edge runtime environments, such as Deno and Cloudflare workers:
The following APIs will continue working, but with limited support for Suspense:
Finally, this API will continue to work for rendering e-mails:
For more information on the changes to server rendering APIs, see the working group post on Upgrading to React 18 on the server, a deep dive on the new Suspense SSR Architecture, and Shaundai Person’s talk on Streaming Server Rendering with Suspense at React Conf 2021.
Updates to TypeScript definitions
If your project uses TypeScript, you will need to update your @types/react and @types/react-dom dependencies to the latest versions. The new types are safer and catch issues that used to be ignored by the type checker. The most notable change is that the children prop now needs to be listed explicitly when defining props, for example:
See the React 18 typings pull request for a full list of type-only changes. It links to example fixes in library types so you can see how to adjust your code. You can use the automated migration script to help port your application code to the new and safer typings faster.
If you find a bug in the typings, please file an issue in the DefinitelyTyped repo.
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:
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 :
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, and external stores. To support React 18, some libraries may need to switch to one of the following APIs:
Updates to Strict Mode
In the future, we’d like to add a feature that allows React to add and remove sections of the UI while preserving state. For example, when a user tabs away from a screen and back, React should be able to immediately show the previous screen. To do this, React would unmount and remount trees using the same component state as before.
This feature will give React better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times. Most effects will work without any changes, but some effects assume they are only mounted or destroyed once.
To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.
Before this change, React would mount the component and create the effects:
With Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode:
Configuring Your Testing Environment
The current testing environment is not configured to support act(…)
To fix this, set globalThis.IS_REACT_ACT_ENVIRONMENT to true before running your test:
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 without any additional configuration.
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. 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.
Immutability Helpers
update is a legacy add-on. Use immutability-helper instead.
Importing
React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it’s easy to implement a fast shouldComponentUpdate() method to significantly speed up your app.
If you mutate data like this:
You have no way of determining which data has changed since the previous copy has been overwritten. Instead, you need to create a new copy of myData and change only the parts of it that need to be changed. Then you can compare the old copy of myData with the new one in shouldComponentUpdate() using triple-equals:
Unfortunately, deep copies are expensive, and sometimes impossible. You can alleviate this by only copying objects that need to be changed and by reusing the objects that haven’t changed. Unfortunately, in today’s JavaScript this can be cumbersome:
While this is fairly performant (since it only makes a shallow copy of log n objects and reuses the rest), it’s a big pain to write. Look at all the repetition! This is not only annoying, but also provides a large surface area for bugs.
update() provides simple syntactic sugar around this pattern to make writing this code easier. This code becomes:
While the syntax takes a little getting used to (though it’s inspired by MongoDB’s query language) there’s no redundancy, it’s statically analyzable and it’s not much more typing than the mutative version.
Updating a value based on its current one
Updating Your React Native App
Congratulations, you’ve written your first React Native app and users are downloading it from the store.
React Native is a rapidly changing framework. New versions are released monthly and breaking changes are common. You should do your best to regularly update to the latest version of React Native so that your app can benefit from the new features and improvements to speed. Going more than a few months without upgrading can result in a painful upgrade process.
In my work at Build.com, I’ve upgraded our React Native app from version 36 to version 45 over a couple big projects. Each upgrade is different based on the libraries you are using, the current version of React Native in your app and the target version that you’re upgrading to.
But given all that, I’ve come up with a process that helps me:
Getting Started
Begin the Upgrade
Upgrading Your Other Libraries
Finishing the Upgrade
Delete Script
We use this Delete Script pretty frequently at work. It fully clears out all of the caches, and re-downloads and installs the libraries. The pod commands are only necessary if you’re using Cocoapods.
Using RN-DIFF
Update to the original post.
rn-diff is a repo that tells you the differences from one version of an app created using the React Native CLI to the next. When you visit the repo, you’re presented with a huge table that lists every major, minor and patch version for React Native and gives you the ability to compare the changes from one version to the next.
The minor version updates appear to be a little more complicated than the patch but, for example, the upgrade from 0.48.4 to 0.49.0 involved a changing a couple dozen lines across 5 files so it’s not that difficult.
I did the last upgrade solely with rn-diff and I would recommended it for everyone unless you have some weird scenario. And I would still guess that rn-diff is easier for most of the weird scenarios.
React v18.0
React 18 is now available on npm!
In our last post, we shared step-by-step instructions for upgrading your app to React 18. In this post, we’ll give an overview of what’s new in React 18, and what it means for the future.
Our latest major version includes out-of-the-box improvements like automatic batching, new APIs like startTransition, and streaming server-side rendering with support for Suspense.
Many of the features in React 18 are built on top of our new concurrent renderer, a behind-the-scenes change that unlocks powerful new capabilities. Concurrent React is opt-in — it’s only enabled when you use a concurrent feature — but we think it will have a big impact on the way people build applications.
We’ve spent years researching and developing support for concurrency in React, and we’ve taken extra care to provide a gradual adoption path for existing users. Last summer, we formed the React 18 Working Group to gather feedback from experts in the community and ensure a smooth upgrade experience for the entire React ecosystem.
In case you missed it, we shared a lot of this vision at React Conf 2021:
Below is a full overview of what to expect in this release, starting with Concurrent Rendering.
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.
What is Concurrent React?
The most important addition in React 18 is something we hope you never have to think about: concurrency. We think this is largely true for application developers, though the story may be a bit more complicated for library maintainers.
Concurrency is not a feature, per se. It’s a new behind-the-scenes mechanism that enables React to prepare multiple versions of your UI at the same time. You can think of concurrency as an implementation detail — it’s valuable because of the features that it unlocks. React uses sophisticated techniques in its internal implementation, like priority queues and multiple buffering. But you won’t see those concepts anywhere in our public APIs.
When we design APIs, we try to hide implementation details from developers. As a React developer, you focus on what you want the user experience to look like, and React handles how to deliver that experience. So we don’t expect React developers to know how concurrency works under the hood.
However, Concurrent React is more important than a typical implementation detail — it’s a foundational update to React’s core rendering model. So while it’s not super important to know how concurrency works, it may be worth knowing what it is at a high level.
A key property of Concurrent React is that rendering is interruptible. When you first upgrade to React 18, before adding any concurrent features, updates are rendered the same as in previous versions of React — in a single, uninterrupted, synchronous transaction. With synchronous rendering, once an update starts rendering, nothing can interrupt it until the user can see the result on screen.
In a concurrent render, this is not always the case. React may start rendering an update, pause in the middle, then continue later. It may even abandon an in-progress render altogether. React guarantees that the UI will appear consistent even if a render is interrupted. To do this, it waits to perform DOM mutations until the end, once the entire tree has been evaluated. With this capability, React can prepare new screens in the background without blocking the main thread. This means the UI can respond immediately to user input even if it’s in the middle of a large rendering task, creating a fluid user experience.
Another example is reusable state. Concurrent React can remove sections of the UI from the screen, then add them back later while reusing the previous state. For example, when a user tabs away from a screen and back, React should be able to restore the previous screen in the same state it was in before. In an upcoming minor, we’re planning to add a new component called that implements this pattern. Similarly, you’ll be able to use Offscreen to prepare new UI in the background so that it’s ready before the user reveals it.
Concurrent rendering is a powerful new tool in React and most of our new features are built to take advantage of it, including Suspense, transitions, and streaming server rendering. But React 18 is just the beginning of what we aim to build on this new foundation.
Gradually Adopting Concurrent Features
Technically, concurrent rendering is a breaking change. Because concurrent rendering is interruptible, components behave slightly differently when it is enabled.
In our testing, we’ve upgraded thousands of components to React 18. What we’ve found is that nearly all existing components “just work” with concurrent rendering, without any changes. However, some of them may require some additional migration effort. Although the changes are usually small, you’ll still have the ability to make them at your own pace. The new rendering behavior in React 18 is only enabled in the parts of your app that use new features.
The overall upgrade strategy is to get your application running on React 18 without breaking existing code. Then you can gradually start adding concurrent features at your own pace. You can use to help surface concurrency-related bugs during development. Strict Mode doesn’t affect production behavior, but during development it will log extra warnings and double-invoke functions that are expected to be idempotent. It won’t catch everything, but it’s effective at preventing the most common types of mistakes.
After you upgrade to React 18, you’ll be able to start using concurrent features immediately. For example, you can use startTransition to navigate between screens without blocking user input. Or useDeferredValue to throttle expensive re-renders.
However, long term, we expect the main way you’ll add concurrency to your app is by using a concurrent-enabled library or framework. In most cases, you won’t interact with concurrent APIs directly. For example, instead of developers calling startTransition whenever they navigate to a new screen, router libraries will automatically wrap navigations in startTransition.
It may take some time for libraries to upgrade to be concurrent compatible. We’ve provided new APIs to make it easier for libraries to take advantage of concurrent features. In the meantime, please be patient with maintainers as we work to gradually migrate the React ecosystem.
For more info, see our previous post: How to upgrade to React 18.
Suspense in Data Frameworks
In React 18, you can start using Suspense for data fetching in opinionated frameworks like Relay, Next.js, Hydrogen, or Remix. Ad hoc data fetching with Suspense is technically possible, but still not recommended as a general strategy.
In the future, we may expose additional primitives that could make it easier to access your data with Suspense, perhaps without the use of an opinionated framework. However, Suspense works best when it’s deeply integrated into your application’s architecture: your router, your data layer, and your server rendering environment. So even long term, we expect that libraries and frameworks will play a crucial role in the React ecosystem.
As in previous versions of React, you can also use Suspense for code splitting on the client with React.lazy. But our vision for Suspense has always been about much more than loading code — the goal is to extend support for Suspense so that eventually, the same declarative Suspense fallback can handle any asynchronous operation (loading code, data, images, etc).
Server Components is Still in Development
Server Components is an upcoming feature that allows developers to build apps that span the server and client, combining the rich interactivity of client-side apps with the improved performance of traditional server rendering. Server Components is not inherently coupled to Concurrent React, but it’s designed to work best with concurrent features like Suspense and streaming server rendering.
Server Components is still experimental, but we expect to release an initial version in a minor 18.x release. In the meantime, we’re working with frameworks like Next.js, Hydrogen, and Remix to advance the proposal and get it ready for broad adoption.
What’s New in React 18
New Feature: Automatic Batching
Batching is when React groups multiple state updates into a single re-render for better performance. Without automatic batching, 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. With automatic batching, these updates will be batched automatically:
New Feature: Transitions
A transition is a new concept in React to distinguish between urgent and non-urgent updates.
Urgent updates like typing, clicking, or pressing, need immediate response to match our intuitions about how physical objects behave. Otherwise they feel “wrong”. However, transitions are different because the user doesn’t expect to see every intermediate value on screen.
For example, when you select a filter in a dropdown, you expect the filter button itself to respond immediately when you click. However, the actual results may transition separately. A small delay would be imperceptible and often expected. And if you change the filter again before the results are done rendering, you only care to see the latest results.
Typically, for the best user experience, a single user input should result in both an urgent update and a non-urgent one. You can use startTransition API inside an input event to inform React which updates are urgent and which are “transitions”:
Updates wrapped in startTransition are handled as non-urgent and will be interrupted if more urgent updates like clicks or key presses come in. If a transition gets interrupted by the user (for example, by typing multiple characters in a row), React will throw out the stale rendering work that wasn’t finished and render only the latest update.
Transitions will opt in to concurrent rendering, which allows the update to be interrupted. If the content re-suspends, transitions also tell React to continue showing the current content while rendering the transition content in the background (see the Suspense RFC for more info).
New Suspense Features
Suspense lets you declaratively specify the loading state for a part of the component tree if it’s not yet ready to be displayed:
Suspense makes the “UI loading state” a first-class declarative concept in the React programming model. This lets us build higher-level features on top of it.
We introduced a limited version of Suspense several years ago. However, the only supported use case was code splitting with React.lazy, and it wasn’t supported at all when rendering on the server.
In React 18, we’ve added support for Suspense on the server and expanded its capabilities using concurrent rendering features.
Suspense in React 18 works best when combined with the transition API. If you suspend during a transition, React will prevent already-visible content from being replaced by a fallback. Instead, React will delay the render until enough data has loaded to prevent a bad loading state.
For more, see the RFC for Suspense in React 18.
New Client and Server Rendering APIs
In this release we took the opportunity to redesign the APIs we expose for rendering on the client and server. These changes allow users to continue using the old APIs in React 17 mode while they upgrade to the new APIs in React 18.
React DOM Client
These new APIs are now exported from react-dom/client :
React DOM Server
These new APIs are now exported from react-dom/server and have full support for streaming Suspense on the server:
The existing renderToString method keeps working but is discouraged.
New Strict Mode Behaviors
In the future, we’d like to add a feature that allows React to add and remove sections of the UI while preserving state. For example, when a user tabs away from a screen and back, React should be able to immediately show the previous screen. To do this, React would unmount and remount trees using the same component state as before.
This feature will give React apps better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times. Most effects will work without any changes, but some effects assume they are only mounted or destroyed once.
To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.
Before this change, React would mount the component and create the effects:
With Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode:
useId is a new hook for generating unique IDs on both the client and server, while avoiding hydration mismatches. It is primarily useful for component libraries integrating with accessibility APIs that require unique IDs. This solves an issue that already exists in React 17 and below, but it’s even more important in React 18 because of how the new streaming server renderer delivers HTML out-of-order. See docs here.
useId is not for generating keys in a list. Keys should be generated from your data.
useTransition and startTransition let you mark some state updates as not urgent. Other state updates are considered urgent by default. React will allow urgent state updates (for example, updating a text input) to interrupt non-urgent state updates (for example, rendering a list of search results). See docs here
useDeferredValue lets you defer re-rendering a non-urgent part of the tree. It is similar to debouncing, but has a few advantages compared to it. There is no fixed time delay, so React will attempt the deferred render right after the first render is reflected on the screen. The deferred render is interruptible and doesn’t block user input. See docs here.
useSyncExternalStore is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. It removes the need for useEffect when implementing subscriptions to external data sources, and is recommended for any library that integrates with state external to React. See docs here.
useSyncExternalStore is intended to be used by libraries, not application code.
useInsertionEffect is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. Unless you’ve already built a CSS-in-JS library we don’t expect you to ever use this. 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. See docs here.
useInsertionEffect is intended to be used by libraries, not application code.
See How to Upgrade to React 18 for step-by-step instructions and a full list of breaking and notable changes.