React js 18 news team React with Dan Abramov
A cool example of how React 18 remounting effects in development (when Strict Mode is on) surfaced a severe bug in the code immediately — which would previously be difficult to notice, debug, or reproduce
--
I am saying that with your current logic, you can get this sequence: - Load tab 1 (no user yet) - Load tab 2 (no user yet) - Tab 1 creates user - Tab 2 creates user So you would have the same exact bug without React 18 in production.
--
This is known as a “race condition”. It’s not React-specific, but it’s a typical mistake in asynchronous code. The fix is to let the server decide whether to create a user (e.g. you can pass some token to both tabs from the server and deduplicate based on it).
--
The difference between having Strict Mode on and off is between “eager bugs” and “on-demand bugs”. Strict Mode immediately forces you to handle the edge cases. This includes bugs you won’t hit in prod today but definitely will as your logic changes. I’ve seen this many times.
--
Dr. Strict and the Multiverse of Bugs (Which You See Immediately Instead of Waiting for Them To Show Up in Production When Somebody Changes the Code)
--
I feel like this hasn’t gotten much fanfare but React 18 solves the whole “how to code split, but also retain SSR’d HTML, but also hydrate without blocking” conundrum with a single (existing) <Suspense> API. I don’t think people quite realize how many hacks can be removed now.
--
Of course, it would be even better if this only included the interactive components and skipped the static parts... But we already talked about this. We want mechanisms to do both so that you don’t have to choose.
One last thing. The benefits of non-blocking hydration in React 18 are much more obvious on a page with a *lot* of content. It doesn’t matter how much content there is! The browser becomes (and remains) responsive after the outer shell hydrates. Concurrent rendering is nice.
--
The only reason I posted the comparison is because Guillermo is praising it for "setting the bar so freaking high" including performance - in current tense. So I thought it'd be fair to bench again - guess it's still too early. Would be happy to revisit after it hits prod!
--
As <Suspense> becomes widely adopted (after data fetching integrations), this perf improvement will come from simply adding a loading state somewhere in your code. It’s essentially a better default for hydration behavior. For more about React 18
--
There’ll be more to optimize. Especially on sandbox-heavy pages. Like Evan pointed out, the INP metric () looks sad. I doubt it’s because React is slow. :) I have one guess for a possible cause. If you want to help, here’s an idea web.dev/inp/
--
In React, there's a restriction on importing Server Components into Client components*. The recommended pattern is to pass it as a child. This pattern is already applied with the `children` prop in layouts - so you don't have to think about it.
--
In the original Server Components demo, we had to carefully work around that we had to refetch all server components from the root during each navigation. Like multi-page apps do. At Meta we relied on their router + Relay to do subtree fetches.
--
It's also critical to the invalidation model that you can invalidate only some Server Components if data changes instead of all. We needed to design a way to fetch data. The first part was Server Context (React RFC coming later) that require RSC Contexts to be serializable.
--
Then we needed to design a router that could support subtree refetches like this, as well as some advanced features I felt was missing (like parallel and conditional routing).
and I worked on a prototype for this to be used as inspiration to complete the story.
--
A realization is also that whenever you go to the server for requests or RSC, we have the opportunity to download where you're going or intercept (e.g. if you're logged out). This was also designed without client-manifests. Less to download and more scalable - Server Routing.
--
When I joined
I worked on refining the model and API so that it could work with Server Context and fit the file based convention. Thanks to and for all the work and great feedback to make this real. It took a number of iterations.
The great work done by
and
on the RSC compiler is being reused for /app/ which will be how you adopt RSC in Next.js. Together with
we're also ironing out a few changes to RSC conventions.