Chapter 3 of 4

Transitions

Marking updates as non-urgent so typing never stutters.

Some updates must feel instant - a keystroke appearing in an input. Others can wait a moment - the filtered results below it. useTransition lets you say which is which.

import { useState, useTransition } from "react";

function SearchPage() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();

  function handleChange(event) {
    setQuery(event.target.value);          // urgent: show the typing

    startTransition(() => {
      setResults(search(event.target.value));   // can be interrupted
    });
  }

  return (
    <>
      <input value={query} onChange={handleChange} />
      <div style={{ opacity: isPending ? 0.6 : 1 }}>
        <Results items={results} />
      </div>
    </>
  );
}

React can interrupt and restart a transition. If another keystroke arrives while the results are still rendering, the in-progress work is abandoned and the newer input wins - so the input never lags behind the user.

isPending

The flag lets you show that something is happening without hiding the old content. Dimming or a small spinner beats replacing results with a skeleton the user has already seen.

useDeferredValue

When you cannot wrap the update - because the value comes from a prop, or from a library - defer the value instead. React renders with the old value first, then re-renders with the new one at a lower priority.

function Results({ query }) {
  const deferredQuery = useDeferredValue(query);
  const isStale = query !== deferredQuery;

  const items = useMemo(() => search(deferredQuery), [deferredQuery]);

  return (
    <div style={{ opacity: isStale ? 0.6 : 1 }}>
      <List items={items} />
    </div>
  );
}

Transitions and Suspense together

An update inside startTransition that causes a component to suspend does not show the fallback. React keeps the current screen visible until the new one is ready, which avoids replacing good content with a spinner during navigation.