Нажмите здесь, чтобы прочитать статью на японском языке:
https://zenn.dev/takuyakikuchi/articles/91ccf7037d6375
Об этой статье
Concurrent React важнее, чем обычная деталь реализации — это фундаментальное обновление основной модели рендеринга React. Поэтому, хотя не так уж важно знать, как работает параллелизм, возможно, стоит знать, что это такое на высоком уровне.
цитата из React v18.0 — Блог React
Вот статья, позволяющая получить высокоуровневый обзор Concurrent React, существенного изменения в основной модели рендеринга React.
Concurrent React — это не функция, а новый механизм
Concurrency — это не функция, как таковая. Это новый закулисный механизм, который позволяет React одновременно готовить несколько версий пользовательского интерфейса.
цитата из React v18.0 — React Blog
Прежде всего, это не функция, как было сказано выше, Concurrent React — это новый механизм (новая модель рендеринга ядра React), позволяющий React иметь несколько версий пользовательского интерфейса, готовых одновременно.
Новое заключается в следующем
- До: рендеринг является коллективным, непрерывным и синхронным.
- Concurrent: рендеринг прерывистый и асинхронный (ключевая характеристика Concurrent React).
С этим новым механизмом
Пользователи получат более плавный пользовательский опыт,
А разработчики смогут более декларативно описывать управление пользовательским интерфейсом на основе состояния загрузки компонентов.
Чтобы более конкретно понять, что это значит, давайте поговорим об одной из особенностей Concurrent React — Suspense.
Suspense
Вот концептуальное объяснение Suspense с простым примером кода.
(Код взят из React Top-Level API — React)
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
Suspense обрабатывает ситуацию, когда внутренний компонент загружается, но еще не готов к рендерингу.
В предыдущем разделе я сказал, что рендеринг прерывается и является асинхронным, что является важной характеристикой Concurrent React.
В этом примере,
- рендеринг
<Comments>
приостановлен на время загрузки (прерывистый) - когда
<Commnets>
завершает загрузку, он отображается (асинхронный рендеринг).
Таким образом, пользовательский интерфейс отображается последовательно, что делает UX плавным.
Вот еще один пример.
function ProfilePage() {
return (
<PageLayout>
<Suspense fallback={<MyProfileSkeleton />}>
<MyProfile />
</Suspense>
<Suspense fallback={<AchievementsSkeleton />}>
<Achievements />
</Suspense>
<Suspense fallback={<OrganizationSkeleton />}>
<Organizations />
</Suspense>
<Suspense fallback={<ContributionsSkeleton />}>
<Contributions />
</Suspense>
</PageLayout>
);
};
В этом примере каждый из них заключен в <Suspense>
.
Это позволяет им иметь независимые скелетные представления и отображаться асинхронно с момента завершения загрузки.
Таким образом, изменяя способ размещения Suspense, можно тонко управлять асинхронным рендерингом пользовательского интерфейса.
Примеры использования Suspense
Теперь давайте рассмотрим конкретный пример использования Suspense.
Ленивая загрузка компонентов с помощью React.lazy
.
Единственный вариант использования на данный момент. (См.: React Top-Level API — React)
// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// Displays <Spinner> until OtherComponent loads
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
Это поддерживается с версии React v.16.6, так что вы, возможно, уже знакомы с этим сценарием использования.
В примере выше отображается содержимое <Spinner>
для отката в ожидании загрузки ленивого компонента <OtherComponent>
с помощью React.lazy
.
React.lazy
— это функция, используемая для выполнения разделения кода, а рендеринг ленивого компонента внутри компонента Suspense
обеспечивает последовательное отображение пользовательского интерфейса.
Расщепление кода — React
Приостановка с получением данных
На данный момент единственным официально поддерживаемым вариантом использования является использование React.lazy
, но видение команды React для Suspense кажется гораздо более масштабным.
Как и в предыдущих версиях React, вы также можете использовать Suspense для разделения кода на клиенте с помощью React.lazy. Но наше видение Suspense всегда было связано не только с загрузкой кода — цель заключается в расширении поддержки Suspense, чтобы в конечном итоге один и тот же декларативный откат Suspense мог обрабатывать любые асинхронные операции (загрузка кода, данных, изображений и т.д.).
Цитата из React v18.0 — React Blog
Одним из таких способов является использование Suspense для получения данных.
Обычный способ
[※Alert: Ниже приведен пример кода с использованием нотации Apollo Client, но Apollo Client в настоящее время не поддерживает Suspense.
Вопрос на Github о поддержке Suspense: https://github.com/apollographql/apollo-client/issues/9627].
// Dog.jsx
function Dogs() {
const { loading, error, data } = useQuery(GET_DOGS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return (
<ul>
{data.dogs.map((dog) => (
<li key={dog.id}>{dog.breed}</li>
))}
</ul>
);
}
В компонентах, выполняющих асинхронную загрузку, «процесс во время загрузки» и «процесс после завершения загрузки» объединены.
Подвесной способ
// Dogs.jsx
function Dogs() {
const { data } = useQuery(GET_DOGS);
return (
<ul>
{data.dogs.map((dog) => (
<li key={dog.id}>{dog.breed}</li>
))}
</ul>
);
};
// App.jsx
function App() {
return (
<React.Suspense fallback={<Spinner />}>
<Dogs />
</React.Suspense>
);
};
Если предыдущая программа была процедурной, например if (isLoading)
, то обработка состояния загрузки стала более декларативной. Это упрощает обязанности компонента, отвечающего за загрузку данных.
Вышеизложенное — это просто идея в качестве примера кода, но если вы хотите начать использовать ее на практике, вы можете начать использовать Suspense для получения данных в React 18 с помощью таких фреймворков, как Relay, Next.js, Hydrogen и Remix. (* Пока не рекомендуется в качестве общей стратегии в том смысле, что это технически возможно).
В будущем они могут предоставить новую базовую функциональность для простого доступа к данным с помощью Suspense без использования фреймворка, поэтому мы с нетерпением ждем будущих обновлений.
См. раздел Suspense во фреймворке данных
Другие примеры использования
Ниже перечислены другие примеры использования, которые являются лишь ссылками.
Компоненты на стороне сервера + Suspense — это функция, которая лично мне очень нравится.
- Возможность рендеринга на стороне сервера в потоковом режимеhttps://reactjs.org/docs/react-api.html#reactsuspense-in-server-side-rendering
- Приостановка во время гидратацииhttps://reactjs.org/docs/react-api.html#reactsuspense-during-hydration
Резюме
Concurrent React — это не только лучший пользовательский опыт, но, как разработчик, я чувствую, что мы должны проектировать для функций, которые будут доступны с Concurrent React.
Я уверен, что как новые возможности Concurrent React, так и поддержка Concurrent в экосистеме React будут все больше и больше обновляться в будущем, поэтому следите за Concurrent React в будущем.
Ссылка
- React 18に備えるにはどうすればいいの? 5分で理解する — Qiita
- React v18.0 — React Blog