Translation: The rolling curtain is still

Original address: dmitripavlutin.com/react-usetr…

In Web applications, UI updates (such as entering a field in an input box and selecting a value from the drop-down box) should be given higher priority, while other operations (such as displaying list filtering content) are given lower priority.

Until now React didn’t provide a tool for prioritizing UI updates.

Fortunately, since React 18(the alpha release of 2021.06), we have been able to enable concurrent mode — Concurrent, which allows UI updates to be marked as high-priority or interruptible low-priority operations.

In this article, you’ll learn how to use useTransition() to mark UI updates as low priority, which is useful for large numbers of non-urgent updates.

1. useTransition()hook

By default, we consider all updates in React to be urgent (i.e., all updates have the same priority). That can lead to a problem – fast updates can be slowed down by a lot of updates.

However, with the new feature concurrency in React 18, you can mark certain updates as interruptible and non-emergent — known as Transitions. This new feature is particularly useful for a large number of UI update operations, such as filtering a large list.

The useTransition() hook function enables users to use concurrent mode features in React components.

Calling const [isPending, startTransition] = useTransitionHook() returns an array with two members:

  • isPending: Specify thistransitionLoading (pending)
  • StartTransition (the callback): Allows the user toThe callbackAny UI updates in thetransitions.
import { useTransition } from 'react';

function MyComponent() {

    const [isPending, startTransition] = useTransition();

    // ...

    const someEventHandler = (event) = > {

        startTransition(() = > {

            // Mark updates as transitions

            setValue(event.target.value);
        });
    }

    return <HeavyComponent value={value} />;

}
Copy the code

In order to be able to use the useTransition() hook, be sure to turn concurrent mode on

2. Urgent mass UI updates

Next, consider an example where all updates are urgent and how these massive updates affect the user experience.

For example, if you have a list of employee names and a search box to find employee names, the component will highlight the names of employees that match the search.

Here is the possible code:

import { useState } from 'react';
export function FilterList({ names }) {
  const [query, setQuery] = useState(' ');
  const changeHandler = ({ target: { value } }) = > setQuery(value);

  return (
    <div>
      <input onChange={changeHandler} value={query} type="text" />
      {names.map((name, i) => (
        <ListItem key={i} name={name} highlight={query} />
      ))}
    </div>
  );
}
function ListItem({ name, highlight }) {
  const index = name.toLowerCase().indexOf(highlight.toLowerCase());
  if (index === -1) {
    return <div>{name}</div>;
  }
  return (
    <div>
      {name.slice(0, index)}
      <span className="highlight">
        {name.slice(index, index + highlight.length)}
      </span>
      {name.slice(index + highlight.length)}
    </div>
  );
}
Copy the code

Online Running Example

Accepts a large list of names. Inside the component, Query is the state variable that contains the query string. The input box is a control component – used to update the Query state variable as user input changes.

Open the sample page and quickly type the query field into the input box, and you may notice typing delays and a noticeable amount of time when the user interface does not respond.

Why does this phenomenon occur and how to solve it?

Updating the values in the input box as the user types is an urgent task that must be performed quickly, and updating the highlighting list of matches is an onerous and non-urgent task.

The number of non-urgent tasks lags behind the light urgent tasks.

The useTransition() hook helps you distinguish between urgent UI updates and non-urgent UI updates.

3. Lots of UI updates as a transition (transitions)

Already improved, you can use useTransition() to tell React which UI updates are emergency (such as updating input field values) and which UI updates are non-emergency transitions (such as updating a list of names that highlight matching queries)

Let’s make the necessary adjustments to the FilterList component.

First, we call the [isPending, startTransition] = useTransition() hook to access startTransition(), and then create a state variable for this transition.

import React, { useState, useTransition } from "react";

export function FilterList({ names }) {
  const [query, setQuery] = useState("");
  const [highlight, setHighlight] = useState("");

  const [isPending, startTransition] = useTransition();

  const changeHandler = ({ target: { value } }) = > {
    setQuery(value);
    startTransition(() = > setHighlight(value));
  };

  return (
    <div>
      <input onChange={changeHandler} value={query} type="text" />
      {isPending ? 'pending' : (
        names.map((name, i) => (
          <ListItem key={i} name={name} highlight={highlight} />)))}</div>
  );
}

function ListItem({ name, highlight }) {
  const index = name.toLowerCase().indexOf(highlight.toLowerCase());
  if (index === -1) {
    return <div>{name}</div>;
  }
  return (
    <div>
      {name.slice(0, index)}
      <span className="highlight">
        {name.slice(index, index + highlight.length)}
      </span>
      {name.slice(index + highlight.length)}
    </div>
  );
}
Copy the code

Run the Transition example online

Open this example using the transitionos feature, and if you type very quickly in the input box, you’ll notice a delayed update of the highlighted list.

React improves the user experience by separating updates for urgent tasks (which update input fields as users type) from rendering for non-urgent tasks (which highlight filtered content).

4. To summarize

The Concurrent mode in React separates urgent tasks from non-urgent tasks, making UI updates more user-friendly.

After enabling the React 18 concurrency feature, you can use the startTransition(callback) function using the useTransition() hook.

UseTransition () allows you to mark mwrite updates as transitions:

const [isPending, startTransition] = useTransition();
startTransition(() = > {
  // Mark updates as transitions
  setStateValue(newValue);
});
Copy the code

P.S.: in addition to using useTranstion(), userDeferredValue(), another new feature in React 18, can remove repeated highlight state variables in

components? Leave your thoughts in the comments section 😊