React постепенно развивает историю с переходами интерфейса, и один из свежих шагов в этом направлении — API addTransitionType. Он позволяет явно пометить, почему именно произошёл transition, чтобы дальше использовать эту причину для разных анимаций и сценариев отображения.

Отдельно интересно то, что эту возможность уже начинает подхватывать и экосистема. В обсуждении интеграции в Next.js описан проп transitionTypes для <Link>, который позволяет передать массив строк с типами перехода. Во время навигации Next.js вызывает React.addTransitionType для каждого указанного типа. Иными словами, теперь можно не просто сделать transition, а ещё и сказать React и браузеру: это переход вперёд, это свайп, это возврат назад или любой другой смысловой тип.

Важно, что такая механика работает только в App Router, потому что именно он опирается на Transitions при навигации. В Pages Router этот API фактически игнорируется: ссылки не ломаются, но transitionTypes там не дают эффекта. Это сделано затем, чтобы можно было создавать общие link-компоненты без лишних развилок в коде.

С точки зрения архитектуры у такого решения есть важный плюс. Обсуждался и другой вариант — передавать в <Link> что-то вроде navigateAction, внутри которого уже вызывался бы addTransitionType. Но это потребовало бы лишней границы между сервером и клиентом: функции нельзя свободно передавать из Server Components в Client Components. Поэтому вариант с массивом строк оказался практичнее.

Что такое addTransitionType

addTransitionType — это новый API React, доступный пока только в Canary и Experimental-каналах. Он позволяет указать причину transition внутри startTransition.

startTransition(() => {
  addTransitionType('my-transition-type');
  setState(newState);
});

Сам по себе вызов ничего не возвращает. Его задача — пометить текущий transition одним или несколькими типами, чтобы затем на эту информацию можно было опереться при анимации интерфейса.

Базовый пример

import { startTransition, addTransitionType } from 'react';
 
function Submit({ action }) {
  function handleClick() {
    startTransition(() => {
      addTransitionType('submit-click');
      action();
    });
  }
 
  return <button onClick={handleClick}>Click me</button>;
}

В этом примере React запоминает, что transition был вызван действием submit-click. Дальше этот контекст можно использовать для настройки поведения ViewTransition.

Как это связано с ViewTransition

Сегодня типы переходов особенно полезны вместе с ViewTransition. React может пробросить тип transition дальше, чтобы анимации зависели не только от факта обновления интерфейса, но и от его причины.

React описывает три основных способа использовать эти типы:

1. Через browser view transition types

Когда ViewTransition активируется из transition, React добавляет собранные transition-типы как browser view transition types. Это позволяет настраивать анимации через CSS-области видимости.

function Component() {
  return (
    <ViewTransition>
      <div>Hello</div>
    </ViewTransition>
  );
}
 
startTransition(() => {
  addTransitionType('my-transition-type');
  setShow(true);
});
:root:active-view-transition-type(my-transition-type) {
  &::view-transition-...(...) {
    ...
  }
}

Так можно по-разному анимировать разные сценарии навигации — например, движение вперёд, назад или появление нового экрана.

2. Через объект классов у ViewTransition

Можно связать определённый transition type с конкретным CSS-классом:

function Component() {
  return (
    <ViewTransition enter={{
      'my-transition-type': 'my-transition-class',
    }}>
      <div>Hello</div>
    </ViewTransition>
  );
}
 
// ...
 
startTransition(() => {
  addTransitionType('my-transition-type');
  setState(newState);
});

Если совпало несколько типов, React объединит их. Если не совпал ни один — будет использован специальный ключ default. А если хотя бы один тип имеет значение none, то ViewTransition вообще отключится для этого случая.

Особенно интересен сценарий навигации в интерфейсах, где важно различать направление:

<ViewTransition
  enter={{
    'navigation-back': 'enter-right',
    'navigation-forward': 'enter-left',
  }}
  exit={{
    'navigation-back': 'exit-right',
    'navigation-forward': 'exit-left',
  }}
>

То есть интерфейс может по-настоящему «понимать», в какую сторону движется пользователь, и анимироваться соответственно.

3. Через события ViewTransition

Есть и императивный путь — через события:

<ViewTransition onUpdate={(inst, types) => {
  if (types.includes('navigation-back')) {
    ...
  } else if (types.includes('navigation-forward')) {
    ...
  } else {
    ...
  }
}}>

Это удобно, если для разных причин transition нужна не только разная CSS-анимация, но и разная логика поведения.

Важные ограничения

У addTransitionType есть несколько особенностей:

  • если объединяются несколько transitions, их типы тоже собираются вместе;
  • одному transition можно назначить сразу несколько типов;
  • после каждого commit типы сбрасываются;
  • если после startTransition показался fallback из <Suspense>, он будет связан с этими типами, а вот последующее раскрытие контента — уже нет.

Это важно учитывать, если вы строите сложные цепочки загрузки и анимации.

Что это даёт Next.js уже сейчас

С практической точки зрения самое интересное здесь — не сам API React, а то, что он начинает находить применение в реальном фреймворке.

В Next.js появляется возможность передавать transitionTypes в ссылки App Router. Это открывает путь к более осмысленным переходам между страницами: не просто «был переход», а «это был свайп», «возврат назад», «переход в карточку», «переход в следующий экран» и так далее.

Примерно так это выглядит концептуально:

<Link href="/profile" transitionTypes={['navigation-forward', 'slide']} />

Во время навигации Next.js вызывает addTransitionType для каждого указанного типа, а дальше эти типы можно использовать в ViewTransition для настройки анимации.

Именно в этом и состоит главный смысл всей истории: React даёт язык для обозначения причины transition, а Next.js начинает применять этот язык к навигации между страницами.

Что пока не решено

При этом даже обсуждаемое решение не закрывает все сценарии. В частности, отдельно отмечалось, что ни navigateAction, ни transitionTypes сами по себе не решают задачу включения view transitions для MPA-навигаций. То есть это важный шаг вперёд, но не финальная точка развития API.

Итог

Получается довольно красивая связка. React вводит addTransitionType — механизм, который позволяет маркировать причину перехода. Next.js, в свою очередь, начинает использовать эту идею в навигации App Router через transitionTypes у <Link>. В результате разработчик получает более выразительный контроль над анимациями и может строить интерфейсы, где переходы ощущаются не как случайный визуальный эффект, а как часть навигационной логики.


Теги: react, nextjs, view-transitions

Источник