DEV Community

Cover image for What's new in react 18, A Quick Overview
farajshuaib
farajshuaib

Posted on

What's new in react 18, A Quick Overview

ReactJS is an open-source JavaScript library that build to develop high-quality user interfaces for both online and mobile apps. In the JavaScript food chain, it is currently the most popular and widely utilised. React was chosen as the preferred JavaScript framework by developers who took part in StackOverflow’s “2020 Developer Survey.”

now react team announced the plan for the next version of React, alongside many of its upcoming features. There was also a release timeline, publicly available alpha, and even a Working Group dedicated to discussing and improving React 18.

Overall, a lot is going on with React, so let’s dive in and explore all the announcements with some additional details!

Let's see what are the new features

  1. Automatic Batching
  2. Start Transition
  3. New Suspense SSR

Automatic Batching

Let first see what is batching?

Batching is grouping multiple state update into a single render to optimize the performance.

Batching occurs when React groups multiple updates together into a single render state for achieving better computational performance. This also prevented the components from rendering “Half-Finished” states where only one state variable was updated before, causing several bugs at times. However, React would not batch the updates every time and rather perform two independent batches. React 18 will be added with a performance improvement update, where it will automatically batch the updates, irrespective of origin, for both the application and the library code. The updates inside of timeouts, promises, or even native event handlers will be batched the same way as the updates inside of React events. This will add an out-of-the-box improvement to the rendering time and even better performance. With this issue addressed in React 18, it makes the batching process more efficient and consistent.

Let see this with a code example.

import { useState, useLayoutEffect } from "react";
import * as ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);

  function handleClick() {
    console.log("=== click ===");
    setCount((prevCount) => prevCount + 1); // Does not re-render yet
    setFlag((prevFlag) => !prevFlag); // Does not re-render yet
    // React will only re-render once at the end (that's batching!)
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
      <LogEvents />
    </div>
  );
}

function LogEvents(props) {
  useLayoutEffect(() => {
    console.log("Commit");
  });
  console.log("Render");
  return null;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Enter fullscreen mode Exit fullscreen mode

We can see, The handleClick has two setState inside it. But when we click the Next button the component renders only a single time. You can see the log in console.
Batching already exists in React 17, But React used to batch update only for browser events, not for callbacks. Check the below code for more details

import { useState, useLayoutEffect } from "react";
import * as ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);

  function handleClick() {
    console.log("=== click ===");
    fetchSomething().then(() => {
      // React 17 and earlier does NOT batch these:
      setCount((prevCount) => prevCount + 1); // Causes a re-render
      setFlag((prevFlaf) => !prevFlaf); // Causes a re-render
    });
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
      <LogEvents />
    </div>
  );
}

function LogEvents(props) {
  useLayoutEffect(() => {
    console.log("Commit");
  });
  console.log("Render");
  return null;
}

function fetchSomething() {
  return new Promise((resolve) => setTimeout(resolve, 100));
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Enter fullscreen mode Exit fullscreen mode

We can see the component is rendered two times in the console when the Next button is clicked. React does not batch update inside promise, setTimeout or any other events. To overcome this Automatic Batching is added in React 18.

Automatic Batching performs batch updates in all events. So we get automatically a better performance compared to the older version of React.
So what we need to do for getting this better performance in our app?
Just update your react version to 18 (as of now 18 Alpha) and add createRoot to your ReactDom render like below

ReactDOM.createRoot(rootElement).render(<App />);
Enter fullscreen mode Exit fullscreen mode

Start Transition

Start Transition classifies the state update into two types

  1. Urgent Updates
  2. Transition Updates (Slow Updates)

Start Transition mainly focus on the User Experience of the app. As updates inside transition run in the background slowly.

During interactions with the user interface for small actions like clicking a button or typing an input, page freezing may occur, disrupting the workflow. In React 18, a new API known as startTransition has been introduced that helps keep the app responsive even during large screen updates. The API substantially improves the user interactions by marking specific movements as “transitions ”. This allows for React to be informed about which updates are important and which are not. Transitions here are interrupted by urgent updates, and the prior irrelevant transitions are dismissed. This enables the UI to ignore secondary updates that might be slower in nature. startTransition moves the updates to the background, consisting of either complex processing or slowed data fetching due to network connectivity.

You can further understand this through a real-world example.

import { startTransition } from 'react';
// Urgent: Show what was typed
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
  // Transition: Show the results
  setSearchQuery(input);
});
Enter fullscreen mode Exit fullscreen mode

setSearchQuery will be interrupted If an urgent update like user interaction events comes in.

React provide a hook for transition with isPending

import { useTransition } from 'react';
const [isPending, startTransition] = useTransition();
Enter fullscreen mode Exit fullscreen mode

isPending can be used to show the loading state to the user. If the transition is in progress.

React recommends using Transition for remote data and large data updates in UI.

New Suspense SSR

This feature is for rendering react components in the server. Now suspense supported for server-side rendering also.

so what's SSR means !

Server-side rendering, also known as SSR, is a component that lets you generate HTML from React components directly on the server and share the HTML with users. Users can see a preview of the page through SSR even before the javascript bundle presents loads and runs. But sometimes, the javascript on the backend takes a long time to get processed, and the time taken is known as Hydrating Time. React 18 will include architectural improvements to the React SSR’s performance. The new update will allow Streaming HTML directly on the server, i.e., the server sends pieces of components as they get rendered using another component known as Suspense, which decides which parts of the application might take longer to load and what shall be rendered directly. Using a selective hydration method, components that are wrapped with Suspense will not block hydration anymore. Every ready component will start hydrating once the browser gets both its content and javascript code.

Discussion (1)

Collapse
kamil7x profile image
Kamil Trusiak

Nice writing ;)

Let me suggest you one thing. If you add language after backticks, you will enable syntax highlighting.
In your case it will be

```tsx
Enter fullscreen mode Exit fullscreen mode

Example:

return (
  <div className="label">Test</div>
);
Enter fullscreen mode Exit fullscreen mode