React 18 was launched on March 29, 2022 and the React team promises this version includes new amazing changes:
Let’s take a look at the new features and extras:
- Upgrading from old versions
- Concurrent renderer
- automatic batching
Upgrading from old versions ♻️
1. Install React 18
You will probably see the warning message ReactDOM.render is no longer supported in React 18 if you try to run the application.
2. Replace the render method
If you are just starting a new project, go ahead and take advantage of the new features listed below
If you are migrating a legacy project, make sure to check the current list of reported bugs in their official repo here
React team sells it as the most important *feature (actually is not a feature, per se) according to them:
❝It’s a new behind-the-scenes mechanism that enables React to prepare multiple versions of your UI at the same time.
Concurrent rendere implementation enables:
- priority queue
- multiple buffering.
But none of this is visible via API for developers. It’s more an under the hood implementation. Important to know that upgrading to React 18, before adding any concurrent features, updates are rendered the same as in previous versions of React.
In short it means that until now once React started rendering it was like it could never be stopped until the user could see the result on the screen, but from now on new possibilities are available such as:
- Cancel extensive ui renders in the middle of the process
- Giving user interactions a higher priority for instance
React concurrency is a core implementation that allows features such as Suspense, transitions, and streaming server rendering to become available and opens the door for new possibilities in the near future.
A new method to replace the old ReactDOM.render in the root of your application.
This makes available the next methods described below.
⚠️ Caution: changing the way to render your application might cause some unexpected behaviours.
Check how to implement it in the first item of this list here.
New method to hydrate a server rendered application. Use it instead of ReactDOM.createRoot or the old ReactDOM.hydrate.
You will also need a server to render (node, denojs, etc…) to render the main file using the ReactDOMServer.
Since this is a bit more complex, I will leave the details for a next article.
I would only recommend using it in legacy projects where new frameworks (such as NextJS or Remix) are not feasible, or you prefer to have control over everthing.
A new easier way to log global errors during rendering or hydration. In the older browsers React will use reportError, or console.error.
There’s not a lot of information about it and even the official documentation shows no result.
But you can try it out yourself:
Automatic batching ✂️
Batching means to arrange (things) in sets or groups so let’s think of “calling functions in groups”.
Probably it’s clearer with the example below:
Simple, isn’t it? This is only possible because of the new core implementation of React 18 concurrent renderer.
The automatic batching is enable by default so if you want to skip it you will need to use the flushSync function
This method allows you to set a block of code as a low priority, so everything else will be executed and rendered first than the piece of code inside the startTransition method.
With chrome developer open you can turn on the CPU throttling to see the effect better
See the complete code here: https://codesandbox.io/s/use-transition-6f5z8n
The main goal here is to hold all the processes and renders until React can execute the code inside the startTransition method so the user typing won’t be stopped improving the user experience.
Of course, you shouldn’t put all functions inside or several startTransition methods because it already has some cost to run itself, so it’s advised to be used only in slow and laggy user input interfaces.
The example above is just an artifical implementation to see how it works, another real world examples are being discussed here: https://github.com/reactwg/react-18/discussions/65
In this case “to defer” means to postpone or basically to hold on something until it can be executed.
Hum… it seems pretty similar to the previous function, doesn’t? 🤔
According to Dan Abramov useDeferredValue is useful when the value comes “from above” and you don’t actually have control over the corresponding setState call.
So another example could be:
See the complete code here: https://codesandbox.io/s/use-deferred-value-4hcg4g?file=/src/App.js
A simple hook to generate unique IDs that are stable between the server and client.
It’s not recommended to generate keys in a list. You should always pick an id from your own list data as explained here.
The following Hooks are provided for library authors to integrate libraries deeply into the React model, and are not typically used in application code according to React documentation, but it’s always nice to know right? 😉
This method was described as:
❝It enables React components to safely and efficiently read from a mutable external source. The API will detect mutations that occur during a render to avoid tearing and it will automatically schedule updates when the source is mutated.
This hook accepts three arguments:
– subscribe: function to register a callback that is called whenever the store changes.
– getSnapshot: function that returns the current value of the store.
– getServerSnapshot: function that returns the snapshot used during server rendering.
It works exactly as useEffect but it is called synchronously before all DOM mutations.
They recommend it to inject styles into the DOM before reading the layout. Remember that this has some limitations to access some data such as useRef or schedule update because of its own nature.
Several minor changes (but not less important) you can find in their official change log. Feel free to take a look at the official changelog: https://github.com/facebook/react/blob/main/CHANGELOG.md#1800-march-29-2022