← Back to Chapters

React 18+ Features

⚛️ React 18+ Features

? Quick Overview

React 18 introduced major upgrades under the hood — especially around concurrent rendering, automatic batching, and new hooks that enhance performance and user experience.

These features make React smarter and more responsive without changing how you write most components.


? Key Concepts

  • Performance Automatic Batching – Groups multiple state updates into one render cycle.
  • UX Concurrent Rendering – Enables interruptible and prioritized updates.
  • Hooks useTransition & useDeferredValue – Manage concurrent UI updates.
  • Async Suspense for Data Fetching – Handles async data gracefully with fallbacks.
  • Server Streaming SSR – Renders pages progressively on the server.

⚙️ 1. Automatic Batching

Before React 18, multiple state updates in async functions caused multiple renders. Now, React batches all updates automatically — even inside timeouts, promises, or event handlers.

? View Code Example
// React 18+ automatic batching example
import React, { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  const handleClick = () => {
    setTimeout(() => {
      // ✅ Both updates are batched together (1 re-render)
      setCount((c) => c + 1);
      setText("Updated!");
    }, 1000);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <p>Text: {text}</p>
      <button onClick={handleClick}>Update</button>
    </div>
  );
}

React intelligently batches these updates into one render, improving performance.

? 2. Concurrent Rendering

Concurrent rendering makes UI updates interruptible. It allows React to pause, resume, or drop low-priority updates — keeping the UI responsive even during heavy work. This works behind the scenes and powers hooks like useTransition().

? 3. useTransition Hook

The useTransition() hook helps distinguish between urgent and non-urgent updates. React defers the latter to keep the UI responsive.

? View Code Example
// Import useTransition for concurrent updates
import React, { useState, useTransition } from "react";

function SearchBox() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  // isPending tells us if a transition is active
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    setQuery(e.target.value); // Urgent update (input field)
    
    startTransition(() => {
      // Simulate slow filter / Non-urgent update
      const filtered = Array(5000).fill("Item")
        .filter(item => item.includes(e.target.value));
      setResults(filtered);
    });
  };

  return (
    <div>
      <input value={query} onChange={handleChange} />
      {isPending ? <p>Loading...</p> : <p>Results: {results.length}</p>}
    </div>
  );
}

isPending indicates when React is deferring a state update, improving perceived performance.

⚡ 4. useDeferredValue Hook

useDeferredValue() delays rendering of a specific value until higher-priority updates (like typing) complete.

? View Code Example
import React, { useState, useDeferredValue } from "react";

function DeferredList({ input }) {
  // Defers using the new input value until urgent tasks finish
  const deferredInput = useDeferredValue(input);
  
  const list = Array(2000).fill("Item")
    .map((_, i) => <li key={i}>{deferredInput} - {i}</li>);

  return <ul>{list}</ul>;
}

export default function App() {
  const [text, setText] = useState("");
  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <DeferredList input={text} />
    </div>
  );
}

This keeps input responsive even when rendering large lists.

? 5. Suspense for Data Fetching

React 18 extends Suspense to data fetching, allowing components to "wait" for async data with fallback UI.

? View Code Example
import React, { Suspense } from "react";
import Profile from "./Profile";

export default function App() {
  return (
    // Fallback UI is shown while Profile data loads
    <Suspense fallback={<p>Loading profile...</p>}>
      <Profile />
    </Suspense>
  );
}

Combined with data frameworks (like React Query), it enables smoother async UX.


? Interactive Simulator: Automatic Batching

See the difference between how React 17 and React 18 handle 3 consecutive state updates inside an asynchronous function (like setTimeout).

Renders Triggered: 0
> System Ready...

? Summary Table

Feature Description Benefit
Automatic Batching Combines multiple state updates Improves performance
Concurrent Rendering Prioritizes important updates Smoother UX
useTransition Defers low-priority state updates Prevents UI lag
useDeferredValue Defers rendering of slow components Maintains interactivity
Suspense Handles async data loading Cleaner async UI

? Tips & Best Practices

  • React 18+ optimizations are mostly automatic — use them naturally with hooks.
  • Prefer useTransition for deferred updates instead of manual throttling.
  • Wrap async components with Suspense for better loading UX.
  • Test new features in concurrent mode environments (React DOM v18+).

? Try It Yourself

  1. Compare batching behavior between React 17 and 18 using async functions.
  2. Build a live search bar using useTransition().
  3. Experiment with useDeferredValue() for large data renders.
  4. Use Suspense with a fake API delay to visualize fallback loading.

Goal: Master React 18+ features that deliver better performance, smoother UI updates, and modern concurrent capabilities.