Yesterday, March 29th, the React team published a post: React 18 is now available on NPM!
Take a look at the new features of React 18.
Concurrent rendering
If I had to sum up the whole React 18 release in one word, it would be concurrency. Concurrency is an underlying feature, and a lot of it is available in this update. Suspense, for example, and the new startTransition() and useDeferredValue() APIS.
Concurrency means that tasks can overlap, a state update doesn’t have to be completely completed before the system moves to the next state, and concurrency allows us to switch back and forth between multiple states. But that doesn’t mean everything is happening at the same time. Instead, you can now pause one task and see something else that is more urgent. Then, once the more urgent tasks are completed, you can jump back to the less urgent tasks and see updates from the more urgent tasks.
React 18 provides tools for using and manipulating concurrent streams. Developers now have more control over rendering priority and order than ever before.
Suspense
A big advantage of React is the readability of the code. Developers can easily open files and read the code from top to bottom to quickly understand what is happening in the component.
However, some of this simplicity is lost when we need to capture and process data. Developers often need to use Apollo or React Query, which provide apis and hooks that allow them to skip complexity.
However, even with these solutions, there are still other issues to deal with. It’s about the way data and load state are intrinsically related. Previously, we had to specify some kind of load state and then write the corresponding JSX for conditional rendering based on it. This means that our UI elements are always associated with the loading state of particular data.
const [loading, setLoading] = useState(true);
ifmyData ! =null {
setLoading(true); } < > {! loading &&<MyComponent />
}
{ loading &&
<Loading />} < >Copy the code
Suspense solves this problem by allowing us to specify fallbacks for UI elements that are not yet ready for display.
<Suspense fallback={<Loading/>} ><MyComponent myData={myData}/>
</Suspense>
Copy the code
Its design is inspired by design principles, especially the concept of skeleton layout, which should be easy for those of you who have done skeleton screens to understand, with UI elements always in place and filled in when the content is ready. This approach helps developers by allowing them to write code that more accurately resembles the actual design, thus narrowing the gap between a prototype and a working application.
This approach makes it easier to redesign the UI of a page, loading together with content, time, and place loaded separately. Because we can add new components (even nested within other components). Or move other elements in or out of a component to quickly rearrange the page layout.
Because the component itself is not inherently bound to a specific chunk of data (the way we used to), it separates UI code from functional code in a way that really prioritizes the design experience.
Suspense can be used for more than data, though — we can also use it for streaming server rendering.
Server side rendering
Server-side rendering is a technique that renders the HTML output of the React component and then sends it to the client before the JS is ready so the user doesn’t get stuck on a completely blank page. Before React 18, this happened in an all-or-nothing fashion, when all the components were ready, the page would update and the user could start interacting with the application.
However, if you have a very slow component, such as a complex data grid, that component can cause a bottleneck.
Now, though, there’s Suspense. As mentioned above, we can wrap a slow component in these tags and tell React to delay loading that component and instead focus on sending other, smaller components first.
This allows users to view content component-by-component as it becomes available on a page, rather than waiting for everything to be ready and then immediately fetching the entire content. You can display the initial HTML immediately and then stream the rest!
Automatic batch processing
Another great new update in React 18 is automatic batching.
What is batch processing?
Previously, batch processing occurred when there were multiple status updates in a single event handler. In that case, React will only re-render once at the end of the function, not every time the state changes. However, this does not happen outside of the event handler. For example, if there are multiple status updates in a fetch call, the code will rerender for each update.
fetch('http://example.com/data.json').then(() = > {
setIsLoading(false);
setData(data);
setError(null);
});
Previously, this code would result in 3 different re-renders, one for each status update.
// Now, these three updates will be packaged into a single re-render.
Copy the code
Updates are now automatically batched. This makes the code more efficient and prevents unnecessary re-rendering. However, if desired, you can also opt out of specific use cases that need to be rerendered.
The new API
startTransition()
When we use the startTransition API, what we’re doing is marking some of the less urgent actions as “transitions” and then telling React to let other more urgent actions take precedence in the rendering timeline.
This is a great update from a user experience perspective. It makes users feel more agile and responsive, while reducing our workload as developers to minimize this pain point. By wrapping those slower, less urgent updates in startTransition.
This means the transition could be interrupted by more pressing updates, with React discarding unfinished, now outdated rendering work and jumping straight to new content. It also means that we won’t have such a situation. Waste time rendering components with outdated and inaccurate data. Alternatively, the information displayed to the user may no longer be correct.
onChange = (e) = > {
const value = e.target.value;
startTransition(() = > {
nonUrgentAction(value);
});
};
Copy the code
useTransition()
Since the entire page will no longer be locked waiting for these lengthy processes, the user may not even realize that the content is still loading!
For this reason, it is also recommended to use isPending to include the values supplied with React 18 as part of the useTransition hook. This hook returns the startTransition function and an isPending for the value set during transition rendering. This allows you to quickly check isPending to determine if you need to adjust the UI, such as disabling the button.
const [isPending, startTransition] = useTransition();
<Button className={isPending ? 'disabled' : 'active'} / >
Copy the code
useDeferredValue()
The new useDeferredValue()API allows us to select specific parts of the UI and intentionally delay updating them so that they don’t slow down the rest of the page. This has two advantages:
1. Control the rendering order
2. The ability to display previous or old values, rather than just loading animations or gray boxes.
As mentioned above, this is a very nice design-oriented update. There’s nothing worse than a page full of loading animations, and a lot of times slightly old data is better than none. This makes our components never feel like they’re loading, even when they’re loading. For users, all they see is data updates.
Here’s an example of how to use it: Let’s say we get value from a data source that updates regularly, but it’s a lot of content that usually takes some time to load. Now, with useDeferredValue, we can allow new data to be fetched in the background and create the illusion of fast, smooth updates by letting our component use old content values for 4000 milliseconds.
const deferredValue = useDeferredValue(value, { timeoutMs: 4000 });
return (
<div>
<MyComponent value={deferredValue} />
</div>
);
Copy the code
ReactDOM.render
Note that in React 18, the syntax used to connect applications to the DOM has been deprecated. Reactdom.render was replaced with reactdom.createroot, which is required to support the new functionality. You can upgrade without changes, and using the reactdom.render code will still work, but you will get an error in the console, and you will not be able to use the new content updated with this new version.
// Old way: reactdom.render (<App />, document.getelementbyid ('root')); // New method: const root = reactdom.createroot (document.getelementById ('root')); root.render(<App/>);Copy the code
No big change
If you’re familiar with past React updates, you’ve probably heard the term “concurrent mode.” It’s important to know that this is outdated. Concurrent mode is no longer the adoption strategy used by React 18. Now called “Concurrency features.” As the React team likes to say, “No concurrency mode, only concurrency functionality!”
It’s worth noting that the new concurrency features are optional, so don’t worry about the impact on the rest of the code.
The attached:
React Getting Started — React
Reference article:
Medium.com/dhiwise/rea…
Dev. To/kathryngray…
React V18.0 — React Blog