Skip to content

Introducing React 18 #4

Introducing React 18 #4
May 27, 2021 · 4 comments · 14 replies

rickhanlonii May 27, 2021


Welcome to the first post in the React 18 workgroup!

This post is intended to provide an overview for the plan for React 18 and serve as a jumping point to other topics in the discussion. At a high level, React 18 includes out-of-the-box improvements to existing features. It is also the first React release to add support for Concurrent Features, which let you improve the user experience in ways that React didn't allow before.

Concurrent Features are opt-in and can be adopted gradually.

Out-of-the-box improvements

React 18 will include out-of-the-box improvements:

Most apps should be able to upgrade to React 18 using the New Root API and immediately see wins from these improvements.

Once on React 18 you can begin to use concurrent features!

Concurrent features

React 18 will be the first React release adding opt-in support for concurrent features such as:

  • startTransition: lets you keep the UI responsive during an expensive state transition.
  • useDeferredValue lets you defer updating the less important parts of the screen.
  • <SuspenseList>: lets you coordinate the order in which the loading indicators appear.
  • Streaming SSR with selective hydration: lets your app load and become interactive faster.

You can start using these features in a small part of your tree without enabling Strict Mode for your entire app.

We will be posting more details on each of these features in the coming weeks.

What about Suspense for data fetching?

The React 18 release includes the foundational work related to <Suspense>, but it will likely not include the recommended data fetching solution yet. A complete solution would need to include Server Components and a built-in Cache, and these projects are still in progress. We expect to see them complete during the 18.x timeline, but not necessarily in the 18.0 initial release.

For full details about <Suspense> in React 18, see this answer.

How to upgrade

Upgrading to React 18 will be the same as any React major such as 16 and 17 (by updating to the latest React 18 release with the additional step of switching from ReactDOM.render to ReactDOM.createRoot. After upgrading, we recommend testing your app as you normally would with an upgrade to flush out any of the issues surfaced by the out-of-the-box improvements.

For specific technical upgrade guides, see:

Once you’ve upgraded to React 18, you can begin using concurrent features:

  • Coming soon: How to gradually use concurrent features
  • Coming soon: Concurrent React for library authors.

Related posts


14 replies

This is a great first post @rickhanlonii! You've done a great job opening questions and then addressing them in the following section.

There is one statement that remains a little thick — to me:

These features are opt-in on a sub-tree basis without enabling StrictMode for your entire app.

If I'm reading it correctly, this means that I can opt-in to Concurrent rendering for only portions of my application. And that previous iterations of this required root-level StrictMode — but no longer. Is that accurate?

If so, is this statement directed at those experimenting with an earlier iterations of Concurrent React? Or is it important information for folks migrating from 17?

3 replies

gaearon May 28, 2021

Yes, this is primarily for folks who tried previous experimental versions where Strict Mode was enabled by default for createRoot. Now it’s back to opt-in, like in 17.

Even if you use Concurrent Features, you don’t have to enable Strict Mode. But it would give you more confidence that they would work reliably so it’s nice if you can enable it (and solve any blockers for that).


chantastic May 28, 2021

…previous experimental versions where Strict Mode was enabled by default for createRoot.

That makes perfect sense. Thank you 🙏


For future readers, there’s a more detailed answer in #34.


Great post to start with @rickhanlonii 🎉

Can we add a section about concurrent Mode before jumping the API (Concurrent Features)? For those who have already tried the experimental versions will be aware of what it is and how it is going to benefit but for others, it can be helpful if we can add more details about it / link to a doc with more information on the same, maybe we can link experimental concurrent mode as well for those who want to read in-depth?

Looks like there is one typo "Once on React 18, you can being begin to use concurrent features!" :)

4 replies

rickhanlonii May 28, 2021
Maintainer Author

@ad1992 thanks for the suggestion! Can you help me understand what we're missing more?

In React 18, there is no concurrent "mode" any more, there are only concurrent features. This is a pretty big difference for those who are familiar with the experimental versions and the current docs where createRoot opted you into a concurrent "mode" where everything was concurrent and strict by default. Instead, we're shipping createRoot sync and loose by default, and it's only when you start using concurrent features that you're opted-into concurrency.

That means concurrency is really just an implementation detail of how React implements the new features we're adding, and that's why we think of it as just two steps:

  • Upgrade to React 18 with createRoot (existing apps will continue to work)
  • Start adding concurrent features (to improve user experience)

Would it be helpful if we wrote a guide like "What happened to concurrent mode?"


@rickhanlonii thanks for the quick reply!
As this is the first release that supports concurrent features and we have two kinds of users

  1. Who have tried experimental concurrent mode, and as you mentioned this will be a big change for them so if we can write a guide on "What happened to concurrent mode?" that would be great as it will not cause any confusion and also make the users aware of how both are different. And also the👇🏻 line will be more clearer as its referring to the experimental version which was the earlier case and not needed anymore.

    These features are opt-in on a sub-tree basis without enabling StrictMode for your entire app.

  2. Who are not aware of experimental concurrent mode, for them this will be a completely new thing so if we can add a section to explain what is meant by the term "concurrent features" with help of some simple examples as an intro that would be great.



That sounds great, I'll work on these updates! Thanks for the suggestions!


drcmda May 28, 2021

@rickhanlonii one of the features i have experimented with before was time slicing (link) which very promising results. will this still be part of react 18, and can it be enabled? from the tests i've ran previously, i didn't use transitions or deferred values i just switched to createRoot and maybe used react-scheduler to prioritise tasks.

3 replies

@drcmda time-slicing is still part of React 18 but we don't do it by default. Instead, you can opt-into time slicing by wrapping updates in startTransition. Transitions run at effectively the same priority as default updates, so the only difference for your use case (i.e. without suspense, outside of a React event) is that it opts-into time-slicing.

This was a key change in the strategy to allow apps to upgrade to React 18 and start using concurrent features in parts of their app, without running the entire app with time-slicing on and forcing users to pay the cost of concurrent compatibility up front. This way, we render updates synchronously by default, and you can select when to run yieldy updates.


drcmda May 28, 2021

nice, just read through this as well #7 (reply in thread) now it's clear to me, thanks!

another question i had is the scheduler and how it fits into the transition phase. can we say "this update is of lesser importance" ? and does it still need to be a transition, so: transition(() => runWithPriority(LowPriority, () => set(...))) ? or will using runWithPriority opt us into concurrent react already?


rickhanlonii May 28, 2021
Maintainer Author

Great question. We've actually updated the way React interacts with the scheduler so it's no longer necessary (or possible) to call the Scheduler directly to control the priority of React updates. The Scheduler package still exists, but it's only used to schedule tasks, and has no bearing on React priorities.

Instead, you can call either flushSync (to effective raise the priority, among other things) or startTransition (to lower the priority, among other things). We'll be posting about these APIs soon with more details.

There are a few reasons for this change. First, we found that interacting these React APIs covered almost all use cases. We also found that interacting with React APIs to control the priority of React updates is not only better ergonomically, but it also simplifies the implementation and layering between React and the Scheduler a ton. Now, React doesn't need to consult the scheduler for the priority of the current running task in order to determine the priority, we can track the priority of the update itself inside of React. Aside from being cleaner and less code, this allows us to use other sources for the priority of the update, like checking the window event type to determine if it's a high priority click event.

So now you just need to do:

startTransition(() => {

This will run the update at a lower priority, with time-slicing and some additional Suspense semantics. Check out the updates time-slicing demo code to see that that this is all we did in the concurrent version (code).


This is an awesome post @rickhanlonii, thanks for the great summary!

I had a question regarding opting into concurrent features on a sub-tree basis. In the case of enabling Streaming SSR with progressive hydration, would the entire tree being rendered get opted into concurrent rendering and therefore need to be StrictMode compliant?

4 replies

Great questions! Just to clarify, you don't need to be StrictMode compliant to use concurrent features. Though it is recommended, in practice we've found everything mostly just works.

For streaming SSR, you opt-into concurrent rendering when using Suspense on both the client and the server. This shouldn't matter for the server, because even though we yield, there are no effects on the server and the server isn't stateful. So while yielding, there's no way for something to change in the middle of rendering.

When we hydrate on the client though, we'll concurrently hydrate anything inside of a Suspense boundary (this is true even with the non-streaming APIs in 18). This is great because it allows you to interact with the content that's been rendered before the entire tree is hydrated. However, if something mutates on the client while we're hydrating, then the new content we're rendering may not match the content that was rendered on the server, causing a mismatch.


Just to clarify, you don't need to be StrictMode compliant to use concurrent features.

Do you mind elaborating more on this point? In the past, this is what I've just assumed (mostly based on a combination of reading these two: and I think it'd be helpful from a migration standpoint to understand which deprecations/warnings are important for adopting concurrent features (i.e. do we need to remove 100% of findDOMNode usages before we can use concurrent feature ____)


Would you mind asking this as a separate Q&A thread?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
6 participants