DEV Community

Cover image for What’s new in React 18?
Rishikesh Vedpathak
Rishikesh Vedpathak

Posted on • Updated on • Originally published at Medium

What’s new in React 18?

What’s new in React 18?

The new version of React is out and it is now available on npm! It has introduced some new, interesting features. You won’t have to change any code or learn a new concept and very importantly it does not break any of your existing code.

👉How To Update

It is fairly simple to update to the latest version of React in your existing project. Follow the below steps to update to React 18,

  1. Update dependencies
    // for npm
    npm install react@18 react-dom@18

    //or for yarn
    yarn add react@18 react-dom@18
Enter fullscreen mode Exit fullscreen mode
  1. Go to your root index.js and make the below changes,
    // Before
    import { render } from 'react-dom';
    const container = document.getElementById('app');
    render(<App />, container);

    // After
    import { createRoot } from 'react-dom/client';
    const container = document.getElementById('app');
    const root = createRoot(container);
    root.render(<App />);
Enter fullscreen mode Exit fullscreen mode

The React.createRoot creates a root running in React 18, which adds all of the improvements of React 18 and allows you to use concurrent features. This will be the root API moving forward.

That’s all! You don’t need to make any other code changes 🥳.


This is the most important concept added in React 18. Concurrency is not a feature, it is an implementation detail. It helps with state update prioritization so that urgent state updates can be prioritized over less urgent/time-consuming/blocking updates.

React 18 — Concurrency

A key property of Concurrent React is that rendering is interruptible. React always process all state updates in the order they were triggered i.e. in a single, uninterrupted, synchronous transaction. With the addition of this concurrency concept, you can tell react that a certain state update has a lower priority than the others, and then react will treat other state updates with higher priority.

You can tell react that a state has a lower priority using one of the new APIs that are newly introduced in React 18 — useTransition and startTransition

👉useTransition and startTransition

useTransition and startTransition let you mark some state updates as not urgent. Other state updates are considered urgent by default.
urgent state updates — updating a text input
non-urgent state updates — rendering a list of search results


  • Since it is a hook this can be used in functional components.

  • It returns an array with two values:

  • isPending: a stateful value for the pending state of the transition

  • startTransition: a function to start the transition


  • This method is designed to be used when useTransition is not available, e.g. class components.

  • This lets you mark updates inside the provided callback as transitions.

See the working examples below. We have a list of two thousand users to be rendered on UI. In the first example, we have used the traditional way of rendering the list whereas in the second example we have used the useTransition hook. You will notice the performance difference while searching for a user.

In the first example, you will notice a bit of lag while typing in the input box, this is because React is waiting for a filtered list state update and then updates the state of the input box.

And in the second example, we are telling React to keep the list update state on low priority which results in performance improvement.

  1. Without prioritization,

    1. With concurrency rendering,

Important Note: *It *is not recommended to wrap every state update with startTransition instead, we should use it only when there is no other solution available to increase the UI performance.


It tells React to show the old state until a newly updated state is ready. This is similar to statrTransition() but can be used where you don’t have complete control over the state updates, e.g. state passed from parent component to a child component. To use this, you simply need to wrap the state variable inside useDeffedValue() , and then your child component will get the old state until an updated value is available.

    const userList = useDeferredValue(props.list);
Enter fullscreen mode Exit fullscreen mode

👉New Hooks for Libraries

React 18 has introduced a few hooks,

  • useSyncExternalStore

  • useInsertionEffect

  • useId

Note: These hooks are intended to be used by libraries, not application code. As an application developer you will probably ever use these hooks.

👉Automatic Batching

Automatic batching allows grouping multiple state updates together so that they get executed as one state update. This results in a single re-render for better performance.

Batching was already present in the older version of React but was limited to React event handlers only. For example, if you have two state updates inside of the same click event, React has always batched these into one re-render. If you run the following code, you’ll see that every time you click, React only performs a single render although you set the state twice:

Batching in the older version of React

With automatic batching React 18 now support state update batching inside promises, setTimeout, native event handlers, or any other event that was not batched in React by default. See the below example,

Automatic batching in React 18

What if I don’t want to batch?

Usually batching is safe, but some code may depend on reading something from the DOM immediately after a state change. For those use cases, you can use ReactDOM.flushSync() to opt-out of batching:

    import { flushSync } from 'react-dom'; // Note: react-dom, not react

    function handleClick() {
      flushSync(() => {
        setCounter(c => c + 1);
      // React has updated the DOM by now
      flushSync(() => {
        setFlag(f => !f);
      // React has updated the DOM by now
Enter fullscreen mode Exit fullscreen mode

👉New Suspense Features

The suspense component is already present in the older version of React. However, the only supported use case was code splitting using React.lazy , and it wasn’t supported at all when rendering on the server. You must have been using the Suspense component to show a fallback component until another component is ready for rendering i.e. lazy loading of components.

    <Suspense fallback={<Spinner />}>
      <LaziComponent />
Enter fullscreen mode Exit fullscreen mode

React 18 allows Suspense work for server-side rendering and in case of data fetching in near future.

👉Server Components

React introduced Server Components however these are still in the research and development phase. These components are meant to render on the server only allowing to perform certain server-side only logic. This will be used to perform tasks on the server that should not run on the client may be for security or performance reasons.

This is an experimental feature and not ready for you to use in your app. We are expecting this to be released in near future. More details are available here.

And more...

  • Check Hybrowlabs for React app development services.

Top comments (0)