Как стать автором
Обновить
1704.87
Timeweb Cloud
То самое облако

React Labs: View Transitions, Activity и другие обновления

Уровень сложностиСредний
Время на прочтение17 мин
Количество просмотров951
Автор оригинала: Ricky Hanlon



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


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


  • View Transitions (переходы между экранами)
  • Activity

А также делимся обновлениями по возможностям, над которыми продолжаем работать:


  • Треки производительности React (React performance tracks)
  • Расширение редактора кода для компилятора
  • Автоматические зависимости эффектов
  • Ссылки на фрагменты (fragment refs)
  • Конкурентные хранилища данных (concurrent stores)

Пример использования View Transitions и Activity в клоне AirBnB

❯ Новые экспериментальные возможности


View Transitions и Activity теперь доступны для тестирования в react@experimental. Эти возможности протестированы в производственной среде и работают стабильно, но финальное API может немного измениться с учетом отзывов пользователей.


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


  • react@experimental
  • react-dom@experimental

Читайте далее, чтобы узнать, как использовать эти возможности в вашем приложении, или ознакомьтесь с новой документацией:


  • <ViewTransition>: компонент для включения анимации перехода между экранами
  • addTransitionType: функция для определения типа перехода
  • <Activity>: компонент для управления отображением элементов интерфейса

View Transitions


View Transitions — это новая экспериментальная возможность, которая упрощает добавление анимации при смене интерфейсов в приложении. В основе этих анимаций лежит новый API startViewTransition, поддерживаемый большинством современных браузеров.


Чтобы включить анимацию для элемента, необходимо обернуть его в новый компонент <ViewTransition>.


// "Что" анимировать
<ViewTransition>
  <div>animate me</div>
</ViewTransition>

Этот новый компонент позволяет явно определять, что анимировать при активации перехода.


Определить, когда запускать анимацию, можно с помощью одного из трех триггеров:


// "Когда" анимировать.

// Переходы
startTransition(() => setState(...));

// Отложенные значения
const deferred = useDeferredValue(value);

// Задержка
<Suspense fallback={<Fallback />}>
  <div>Loading...</div>
</Suspense>

По умолчанию для таких переходов используются стандартные CSS-анимации (обычно это плавное переключение). Однако можно использовать псевдоселекторы для настройки того, как будет происходить анимация. Например, чтобы изменить анимацию для всех переходов сразу, необходимо использовать *:


// "Как" анимировать
::view-transition-old(*) {
  animation: 300ms ease-out fade-out;
}
::view-transition-new(*) {
  animation: 300ms ease-in fade-in;
}

Когда DOM обновляется из-за активации анимации — например, при использовании startTransition, useDeferredValue или переключении содержимого с помощью Suspense — React применяет декларативные эвристики, чтобы автоматически определить, какие компоненты <ViewTransition> нужно активировать для анимации. Затем браузер выполняет анимацию, определенную в CSS.


Если вы знакомы с API View Transition в браузере и хотите узнать, как React поддерживает его, ознакомьтесь с разделом "Как работает <ViewTransition>" в документации.


В этой статье мы рассмотрим несколько примеров использования View Transitions.


Начнем с приложения, в котором не анимируются следующие взаимодействия:


  • Клик по видео для просмотра деталей
  • Клик по кнопке "Назад" для возврата к ленте
  • Ввод текста для фильтрации видео


View Transitions не заменяют анимации, основанные на CSS и JS.
View Transitions предназначены для анимации интерфейсных переходов, таких как навигация, раскрытие/скрытие или изменение порядка элементов. Они не предназначены для замены всех анимаций в приложении.
В нашем примере уже реализованы анимации клика по кнопке "Нравится" и отображения состояния загрузки в резервном контенте Suspense. Это хорошие примеры использования анимаций CSS, которые анимируют конкретный элемент.

Анимация навигации


В нашем приложении используется роутер с поддержкой Suspense, и переключения между страницами уже помечены как переходы (transitions). Это означает, что навигация выполняется с помощью startTransition:


function navigate(url) {
  startTransition(() => {
    go(url);
  });
}

startTransition — это триггер View Transition, поэтому мы можем добавить <ViewTransition>, чтобы анимировать переходы между страницами:


// "Что" анимировать
<ViewTransition key={url}>
  {url === '/' ? <Home /> : <TalkDetails />}
</ViewTransition>

Когда url меняется, рендерятся компонент <ViewTransition> и новый интерфейс. Поскольку <ViewTransition> обновляется внутри startTransition, он активируется для выполнения анимации.


По умолчанию, для View Transitions используется стандартная анимация переключения (cross-fade) от браузера. Добавив это в пример, мы получаем плавное переключение при переходе между страницами:



Отключение анимации <ViewTransition>
В нашем примере мы оборачиваем корневой компонент приложения в <ViewTransition> для удобства, но это приведет к тому, что все переходы в приложении будут анимироваться, что может вызвать нежелательные эффекты.
Чтобы исправить это, мы оборачиваем дочерние компоненты в <ViewTransition> с пропом default="none", чтобы каждая страница управляла анимацией самостоятельно:

// Layout.js
<ViewTransition default="none">
  {children}
</ViewTransition>

На практике навигацию следует выполнять с помощью пропов enter и exit или типов переходов (transition types).

Настройка анимаций


По умолчанию <ViewTransition> использует стандартную анимацию переключения от браузера.


Для настройки анимации используются специальные пропы <ViewTransition>, позволяющие указать, какие анимации выполнять в зависимости от того, как активируется <ViewTransition>.


Например, мы можем замедлить стандартную (default) анимацию следующим образом:


<ViewTransition default="slow-fade">
  <Home />
</ViewTransition>

И определить анимацию slow-fade в CSS, используя классы view transitions:


::view-transition-old(.slow-fade) {
    animation-duration: 500ms;
}

::view-transition-new(.slow-fade) {
    animation-duration: 500ms;
}

Теперь анимация переключения происходит медленнее:



Смотрите раздел "Стилизация View Transitions" для подробного руководства по стилизации <ViewTransition>.


Переходы с общими элементами


Когда на двух страницах используется один и тот же элемент, хочется сделать плавный переход между ними.


Для этого можно добавить уникальное имя компоненту <ViewTransition>:


<ViewTransition name={`video-${video.id}`}>
  <Thumbnail video={video} />
</ViewTransition>

Теперь миниатюра видео плавно переключается между двумя страницами.



По умолчанию React автоматически генерирует уникальные имена (name) для каждого элемента, участвующего в переходе. Если React обнаруживает, что один <ViewTransition> с определенным именем удаляется, а другой с таким же именем добавляется, он активирует переход для общего элемента.


Больше информации можно найти в разделе "Анимация общих элементов" документации.


Анимация на основе типа перехода


Иногда элементы нужно анимировать по-разному в зависимости от того, что вызвало переход. Для этого был добавлен новый API addTransitionType, который позволяет указать причину перехода:


function navigate(url) {
  startTransition(() => {
    // Устанавливаем тип перехода для "навигации вперед"
    addTransitionType('nav-forward');
    go(url);
  });
}
function navigateBack(url) {
  startTransition(() => {
    // Устанавливаем тип перехода для "навигации назад"
    addTransitionType('nav-back');
    go(url);
  });
}

Добавим плавное переключение заголовка между "6 Videos" и "Back":


<ViewTransition
  name="nav"
  share={{
    'nav-forward': 'slide-forward',
    'nav-back': 'slide-back',
  }}>
  {heading}
</ViewTransition>

Проп share позволяет определить анимацию в зависимости от типа перехода. Когда переход запускается с типом nav-forward, используется класс slide-forward. Если переход выполняется с типом nav-back, активируется анимация slide-back. Определим эти анимации в CSS:


::view-transition-old(.slide-forward) {
    /* При переходе вперед, "старая" страница должна смещаться влево. */
    animation: ...
}

::view-transition-new(.slide-forward) {
    /* При переходе вперед, "новая" страница должна выдвигаться справа. */
    animation: ...
}

::view-transition-old(.slide-back) {
    /* При переходе назад, "старая" страница должна смещаться вправо. */
    animation: ...
}

::view-transition-new(.slide-back) {
    /* При переходе назад, "новая" страница должна выдвигаться слева. */
    animation: ...
}

Теперь мы можем анимировать заголовок вместе с миниатюрой в зависимости от типа перехода:



Анимация Suspense


Suspense также активирует View Transitions.


Чтобы анимировать переход от запасного контента к основному, достаточно обернуть Suspense в <ViewTransition>:


<ViewTransition>
  <Suspense fallback={<VideoInfoFallback />}>
    <VideoInfo />
  </Suspense>
</ViewTransition>

Запасной контент будет плавно переходить в основной. Нажмите на видео, и информация о нем будет отображаться с анимацией:



Мы также можем определять кастомные анимации, используя exit для запасного контента и enter для основного контента:


<Suspense
  fallback={
    <ViewTransition exit="slide-down">
      <VideoInfoFallback />
    </ViewTransition>
  }
>
  <ViewTransition enter="slide-up">
    <VideoInfo id={id} />
  </ViewTransition>
</Suspense>

Определим анимации slide-down и slide-up с помощью CSS:


::view-transition-old(.slide-down) {
  /* Сдвигаем запасной контент вниз */
  animation: ...;
}

::view-transition-new(.slide-up) {
  /* Сдвигаем основной контент вверх */
  animation: ...;
}

Теперь запасной контент заменяется основным с помощью анимации сдвига:



Анимация списков


<ViewTransition> можно использовать для анимации списков элементов при их перестановке/добавлении/удалении, например, в списке с возможностью поиска:


<div className="videos">
  {filteredVideos.map((video) => (
    <ViewTransition key={video.id}>
      <Video video={video} />
    </ViewTransition>
  ))}
</div>

В данном случае для активации ViewTransition можно использовать useDeferredValue:


const [searchText, setSearchText] = useState('');
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);

Теперь элементы анимируются по мере ввода текста в строку поиска:



Итоговый результат


Добавив несколько компонентов <ViewTransition> и несколько строк CSS, мы легко реализовали все анимации, которые хотели.


Мы в восторге от возможностей View Transitions и уверены, что они позволят создавать еще более качественные и динамичные приложения. Эти возможности уже готовы к тестированию в экспериментальной версии React.


Удалим slow fade и посмотрим на итоговый результат:



Для дополнительной информации о процессе разработки View Transitions, смотрите: #31975, #32105, #32041, #32734, #32797, #31999, #32031, #32050, #32820, #32029, #32028 и #32038 от @sebmarkbage.


Activity


В предыдущих обновлениях мы рассказывали о том, что занимаемся разработкой API, которое позволяет компонентам быть визуально скрытыми и деприоритизированными. Это сохраняет состояние интерфейса, при этом снижая затраты на производительность по сравнению с удалением компонентов или их скрытием с помощью CSS.


Теперь мы готовы представить этот API и объяснить, как он работает, чтобы можно было начать тестировать его в экспериментальных версиях React.


<Activity> — это новый компонент для скрытия и отображения частей интерфейса:


<Activity mode={isVisible ? 'visible' : 'hidden'}>
  <Page />
</Activity>

Когда Activity видим (visible), он рендерится как обычный компонент. Когда скрыт (hidden), он размонтируется, но сохраняет свое состояние и продолжает рендериться с более низким приоритетом по сравнению с видимыми элементами на экране.


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


Рассмотрим несколько кейсов, улучшивших примеры с View Transition, приведенные выше.


Эффекты не запускаются, когда компонент Activity скрыт.
Когда компонент <Activity> скрыт, эффекты размонтируются. В концептуальном плане компонент размонтирован, но React сохраняет его состояние для последующего использования.
На практике это работает, как ожидается, если следовать рекомендациям из руководства "You Might Not Need an Effect". Чтобы заранее выявить проблемные эффекты, мы рекомендуем использовать <StrictMode>, который будет принудительно выполнять размонтирование и монтирование Activity для выявления неожиданных побочных эффектов.

Восстановление состояния с помощью Activity


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


function App() {
  const { url } = useRouter();

  return (
    <>
      {url === '/' && <Home />}
      {url !== '/' && <Details />}
    </>
  );
}

Однако это означает, что если пользователь перейдет на другую страницу, все данные будут потеряны. Например, на странице <Home /> есть <input> и при уходе с нее это поле будет размонтировано, и весь введенный пользователем текст будет потерян.


Activity позволяет хранить состояние, пока пользователь перемещается между страницами, так что при возвращении он сможет продолжить с того места, где остановился. Это достигается с помощью оборачивания части дерева в компонент <Activity> и переключения режима (mode):


function App() {
  const { url } = useRouter();

  return (
    <>
      <Activity mode={url === '/' ? 'visible' : 'hidden'}>
        <Home />
      </Activity>
      {url !== '/' && <Details />}
    </>
  );
}

Раньше, когда вы искали видео, выбирали его и возвращались, фильтр поиска сбрасывался. С Activity фильтр автоматически восстанавливается.


Попробуйте найти видео, выбрать его и нажать "Назад":



Предварительный рендеринг с помощью Activity


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


Например, сейчас в нашем приложении возникает задержка из-за загрузки данных для каждого видео при его выборе. Мы можем улучшить этот процесс, заранее подготовив все страницы в скрытом <Activity> до того, как пользователь перейдет на них:


<ViewTransition>
  <Activity mode={url === '/' ? 'visible' : 'hidden'}>
    <Home />
  </Activity>
  {videos.map(({id}) => (
    <Activity key={id} mode={videoId === id ? 'visible' : 'hidden'}>
      <Details id={id}/>
    </Activity>
  ))}
<ViewTransition>

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



Серверный рендеринг с использованием Activity


При использовании Activity на страницах с серверным рендерингом (server side rendering, SSR) доступны дополнительные оптимизации.


Если часть страницы рендерится с параметром mode="hidden", она не включается в ответ сервера. Вместо этого React планирует клиентский рендеринг содержимого внутри Activity, пока остальная часть страницы гидратируется (hydrates), при этом приоритет отдается видимому контенту.


Для элементов, рендерящихся с mode="visible", React будет снижать приоритет гидратации содержимого внутри Activity, аналогично тому, как это происходит с Suspense. Если пользователь взаимодействует со страницей, при необходимости приоритет гидратации будет повышен.


Это достаточно продвинутые сценарии использования, но они демонстрируют дополнительные преимущества, которые предоставляет Activity.


Будущие режимы Activity


В будущем мы планируем добавить в Activity новые режимы.


Например, одна из распространенных ситуаций — отображение модального окна, когда предыдущая "неактивная" страница остается видимой за "активным" модальным представлением. Текущий режим hidden не подходит для такого сценария, поскольку скрывает содержимое и исключает его из серверного рендеринга.


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


Другой потенциальный режим для Activity — автоматическое уничтожение состояния скрытых компонентов, если объем используемой памяти становится слишком большим. Поскольку компонент размонтирован, может быть лучше освободить память, удаляя состояние редко используемых скрытых частей приложения.


Эти направления все еще находятся в стадии исследования, и мы будем делиться дополнительной информацией по мере продвижения работы. Подробнее о текущих возможностях Activity можно узнать в документации.


❯ Новые возможности, находящиеся в разработке


Мы продолжаем работать над возможностями, которые помогут разработчикам решать распространенные задачи.


Пока мы тестируем различные подходы, некоторые экспериментальные API могут появляться в открытых PR. Однако важно понимать, что на этапе экспериментов решения могут меняться или полностью исключаться.


Если делиться деталями слишком рано, это может вызвать путаницу в сообществе, поэтому мы предпочитаем рассказывать о текущих задачах, не фиксируя конкретные решения.


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


❯ Треки производительности


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


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





Сейчас существует несколько известных проблем, которые мы планируем решить, таких как производительность и проблемы с отслеживанием работы через отложенные (suspended) деревья в планировщике. Поэтому пока эта функция не готова к использованию. Мы также продолжаем собирать отзывы от первых пользователей, чтобы улучшить дизайн и удобство работы с треками.


Как только эти вопросы будут решены, мы опубликуем экспериментальную документацию и сообщим, что функция готова для тестирования.


❯ Автоматические зависимости эффектов


Когда мы выпустили хуки, у нас было три основные цели:


  • Обмен кодом между компонентами: хуки заменили такие паттерны, как render props и компоненты более высокого порядка (higher order components, HOC), позволяя повторно использовать логику с состоянием без изменения иерархии компонентов
  • Мыслить в терминах функций, а не жизненных циклов: хуки позволяют разделить один компонент на более мелкие функции, основываясь на взаимосвязанных частях логики (например, настройка подписки или загрузка данных), вместо того, чтобы разбивать код по методам жизненного цикла
  • Поддержка компиляции до выполнения: хуки были спроектированы с учетом поддержки компиляции до выполнения, минимизируя проблемы, связанные со случайным снижением производительности, вызванной методами жизненного цикла и ограничениями классов

С момента появления хуков, они эффективно решают задачу повторного использования кода между компонентами. Теперь хуки стали предпочтительным способом обмена логикой между компонентами, и случаи использования render props и HOC встречаются редко. Кроме того, хуки успешно поддерживают такие функции, как быстрое обновление (fast refresh), которые были невозможны при использовании классов.


Эффекты могут быть сложными


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


Мы выяснили, что часто путаница возникает из-за использования эффекта без особой необходимости. В руководстве "You Might Not Need an Effect" описано множество случаев, когда эффекты не являются правильным решением. Однако даже в тех случаях, когда эффект действительно подходит для задачи, понять его сложнее, чем жизненные циклы классовых компонентов.


Мы считаем, что одной из причин путаницы является то, что разработчики склонны рассматривать эффекты с точки зрения компонента (как жизненный цикл), а не с точки зрения того, что делает сам эффект.


Рассмотрим пример из документации:


useEffect(() => {
  const connection = createConnection(serverUrl, roomId);
  connection.connect();
  return () => {
    connection.disconnect();
  };
}, [roomId]);

Многие прочтут этот код как "при монтировании подключиться к комнате с указанным roomId. При изменении roomId, отключиться от старой комнаты и подключиться к новой". Однако это рассуждение в терминах жизненного цикла компонента, что требует учета каждого состояния жизненного цикла для правильного написания эффекта. Это может быть трудным, поэтому эффекты кажутся более сложными, чем жизненные циклы классов, когда их рассматривают в таком ключе.


Эффекты без зависимостей


Лучше всего исходить из самого эффекта. Эффект ничего не знает о жизненном цикле компонента, он лишь описывает, как запустить синхронизацию и как ее остановить. Когда пользователи начинают рассматривать эффекты таким образом, их становится легче писать, и они становятся более надежными при многократном запуске и остановке.


Мы потратили много времени на изучение того, почему эффекты воспринимаются с точки зрения компонента, и считаем, что одной из причин является массив зависимостей. Поскольку вам нужно указывать зависимости, они всегда на виду, напоминают, на что вы "реагируете", и автоматически заставляют думать по принципу "делать это, когда изменятся эти значения".


Когда мы выпустили хуки, мы знали, что сможем упростить их использование с помощью предварительной компиляции. С React Compiler в большинстве случаев теперь можно избежать необходимости самостоятельно писать useCallback и useMemo. Для эффектов компилятор может автоматически определять зависимости:


useEffect(() => {
  const connection = createConnection(serverUrl, roomId);
  connection.connect();
  return () => {
    connection.disconnect();
  };
}); // зависимости будут добавлены компилятором автоматически

React Compiler самостоятельно определит и добавит все необходимые зависимости эффекта. Это помогает закрепить правильную модель мышления при написании эффектов, которые могут выполняться в любое время для синхронизации состояния компонента или хука с чем-то другим.


Мы надеемся, что автоматическое добавление зависимостей не только упростит написание кода, но и сделает его более понятным, побуждая вас думать о том, что делает сам эффект, а не на что он должен реагировать.


❯ Расширение для редактора кода


На этой неделе мы представили пробную версию React Compiler, а в ближайшие месяцы планируем выпустить первую стабильную версию с поддержкой SemVer.


Мы также начали исследовать способы использования React Compiler для предоставления информации, которая может помочь лучше понять и отлаживать код. Одной из идей, которую мы начали реализовывать, является новое экспериментальное расширение для IDE на базе LSP, поддерживаемое React Compiler, аналогичное расширению, использованному в докладе Лорен Тан на React Conf.


Мы предполагаем, что с помощью статического анализа компилятора можно предоставить больше информации, предложений и возможностей для оптимизации кода прямо в вашей IDE. Например, мы можем показывать диагностику для кода, нарушающего правила React, выводить подсказки о том, были ли компоненты и хуки оптимизированы компилятором, или показывать CodeLens для автоматически добавленных зависимостей эффекта.


❯ Ссылки на фрагменты


Многие DOM-API, такие как управление событиями, позиционирование и фокусировка, трудно использовать в React. Это часто заставляет разработчиков обращаться к эффектам и управлению несколькими ссылками (рефами, refs), используя такие API, как findDOMNode (удален в React 19).


Мы изучаем возможность добавления ссылок на фрагменты, которые будут указывать на группу DOM-элементов, а не только на один элемент. Мы надеемся, что это упростит управление несколькими дочерними элементами и сделает код React более удобным для компоновки при работе с DOM-API.


❯ Анимации, управляемая жестами


Мы также работаем над улучшением View Transitions для поддержки анимации с помощью жестов, таких как свайп (swiping) для открытия меню или прокрутка карусели изображений.


Жесты создают новые проблемы по нескольким причинам:


  • Жесты непрерывны: анимация привязана ко времени касания пальцем экрана, а не запускается и идет до завершения
  • Жесты не завершаются: когда вы убираете палец, анимация может либо завершиться, либо вернуться в исходное состояние (например, если меню было открыто не до конца), в зависимости от прогресса
  • Жесты инвертируют старое и новое: во время анимации страница, с которой мы уходим, должна оставаться "живой" и интерактивной. Это инвертирует модель переходов в браузере, где "старое" состояние — это снимок, а "новое" состояние — это активный DOM

Мы уверены, что нашли подход, который хорошо работает, и возможно введем новый API для управления жестовыми переходами. На данный момент мы сосредоточены на завершении работы над <ViewTransition>, а жесты рассмотрим позже.


❯ Конкурентные хранилища


Когда мы выпустили React 18 с поддержкой конкурентного рендеринга (concurrent rendering), мы также представили хук useSyncExternalStore, чтобы сторонние библиотеки хранилищ (store libraries), не использующие состояние или контекст React, могли поддерживать конкурентный рендеринг, запуская синхронный рендеринг при обновлении хранилища.


Однако использование useSyncExternalStore имеет свои недостатки, так как оно вынуждает отказываться от таких конкурентных функций, как переходы, и заставляет отображать резервный контент Suspense даже при наличии основного контента.


Теперь, с выходом React 19, мы вернулись к этой проблеме и разрабатываем примитив, который полностью поддерживает конкурентные внешние хранилища с помощью следующего API:


const value = use(store);

Наша цель — позволить считывать внешнее состояние во время рендеринга без его нарушения и обеспечить полную совместимость со всеми конкурентными возможностями React.




Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале

Теги:
Хабы:
+10
Комментарии1

Публикации

Информация

Сайт
timeweb.cloud
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия
Представитель
Timeweb Cloud