React Переходы с отложенным обновлением

Переходы с отложенным обновлением в React — это механизм (появился в React 18), позволяющий помечать некоторые обновления состояния как "не срочные". Это нужно, чтобы React мог приостановить их выполнение и сначала обработать более важные (срочные) обновления — так интерфейс остаётся отзывчивым даже при тяжёлых вычислениях.

Реализовать данный механизм позволяет хук useTransition.


Когда использовать переходы с отложенным обновлением?

Переходы с отложенным обновлением используются, когда у вас есть:

  • Медленная операция, которая может заморозить интерфейс
  • Обновления, которые не критичны немедленно
  • Результаты поиска, занимающие некоторое время для отображения

Как это работает

  1. Вы оборачиваете изменение состояния в startTransition (из хука useTransition).
  2. React отмечает это обновление как "переход" — то есть некритичное по времени.
  3. Если в этот момент возникает срочное действие (например, ввод в поле), React приостанавливает "переход" и сначала обрабатывает срочное обновление.
  4. Когда интерфейс свободен, React возвращается к отложенному обновлению и завершает его.

Простой пример

Вот простой пример, демонстрирующий, как использовать переходы с отложенным обновлением в поиске:

Пример


import { useState, useTransition } from 'react';

function SearchBar() {
  const [text, setText] = useState('');
  const [results, setResults] = useState('');
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    // Срочно: мгновенно обновить ввод
    setText(e.target.value);

    // Не срочно: обновление результатов поиска
    startTransition(() => {
      setResults(e.target.value);
    });
  };

  return (
    <div>
      <input value={text} onChange={handleChange} />
      {isPending ? (
        <p>Загрузка...</p>
      ) : (
        <p>Результаты поиска для: {results}</p>
      )}
    </div>
  );
}

В этом примере:

  • Поле ввода обновляется сразу (срочное обновление)
  • Обновление результатов поиска отмечено как отложенный переход (несрочное)
  • Сообщение загрузки отображается пока выполняется отложенный переход

Пример из реального мира

Более практичный пример с медленно работающим поиском:

Пример


import { useState, useTransition } from 'react';

function SearchResults({ query }) {
  // Имитация медленных результатов поиска
  const items = [];
  if (query) {
    for (let i = 0; i < 1000; i++) {
      items.push(<li key={i}>Результат для {query} - {i}</li>);
    }
  }
  return <ul>{items}</ul>;
}

function App() {
  const [input, setInput] = useState('');
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    // Срочно: обновление поля ввода
    setInput(e.target.value);

    // Не срочно: обновление результатов поиска
    startTransition(() => {
      setQuery(e.target.value);
    });
  };

  return (
    <div>
      <input 
        type="text" 
        value={input} 
        onChange={handleChange} 
        placeholder="Наберите для поиска..."
      />
      {isPending && <p>Загрузка результатов...</p>}
      <SearchResults query={query} />
    </div>
  );
}

Как работает этот пример:

  • Когда вы вводите текст в поле, оно обновляется моментально
  • Обновление результатов поиска помещено в startTransition
  • Пока идет обновление результатов, isPending равен true
  • Интерфейс остается отзывчивым даже при большом количестве результатов

Хук useTransition

Хук useTransition возвращает два элемента:

  • isPending: показывает, активен ли сейчас отложенный переход
  • startTransition: функция для маркировки обновлений как отложенный переход
Примечание: Используйте переходы с отложенным обновлением только для несрочных обновлений. Например, ввод текста в поле должен быть срочным, а фильтрация большого списка может стать отложенным переходом.