Хук оптимизации производительности useTransition в React

Хук оптимизации производительности useTransition позволяет нам обновлять стейты без блокировки графического интерфейса.

С помощью данного хука мы можем задать обновлению какого-нибудь стейта низкий приоритет, что позволит обновлению других стейтов иметь высокий приоритет и выполняться без задержек.

В качестве примера можно привести фильтрацию выпадающего списка товаров при введении пользователем символов в поле поиска. Конечно, сам список может отображаться с какой-то задержкой, но нам бы не хотелось, чтобы символы вводились в поле поиска с задержкой.

Давайте посмотрим, как в таких случаях нам может помочь хук useTransition. Предположим, у нас есть кусок кода основного комопонента. Давайте его проанализируем:

App.jsximport { useTransition } from 'react';
import { useState } from 'react';

function App() {
  const [isPending, startTransition] = useTransition();
  const [filterTerm, setFilterTerm] = useState('');
  
  const filteredProducts = filterProducts(filterTerm);
  
  function updateFilterHandler(event) {
    startTransition(() => {
      setFilterTerm(event.target.value);
    });
  }
 
  return (
    <div>
      <input type="text" onChange={updateFilterHandler} />
      <ProductList products={filteredProducts} />
    </div>
  );
}

Здесь мы видим две переменные для useTransition. Переменная isPending содержит булево значение и показывает закончен ли процесс обновления, а startTransition функцию, которая и позволяет снизить приоритет обновления:

App.jsxconst [isPending, startTransition] = useTransition();

Также у нас есть стейт filterTerm, в котором хранится вводимое в поле ввода выражение и функция setFilterTerm для его установки:

App.jsxconst [filterTerm, setFilterTerm] = useState('');

При вводе символов в инпут у нас каждый раз вызывается функция updateFilterHandler, в которой происходит обновление filterTerm. Именно здесь мы применяем наш хук useTransition, оборачивая функцию установки setFilterTerm в startTransition следующим образом:

App.jsxfunction updateFilterHandler(event) {
  startTransition(() => {
    setFilterTerm(event.target.value);
  });
}

Таким образом, мы установили для обновления стейта filterTerm низкий приоритет и наше поле ввода останется отзывчивым.

При помощи переменной isPending мы можем показать пользователю, что обновление списка еще в процессе. Выведем эту информацию под полем ввода, пока список обновляется:

App.jsxreturn (
  <div>
    <input type="text" onChange={updateFilterHandler} />
    {isPending && <p>updating ...</p>}
    <ProductList products={filteredProducts} />
  </div>
);