Transition과 Suspense-enabled Router
- 리액트 프레임워크나 라우터를 구축하는 경우, 페이지 탐색을 Transition으로 표시하는 것이 좋다.
- Suspense-enabled router 와 Transition은 직접적인 연관성보다는 상호보완적인 관계라고 보면 좋음. 즉, Router가 페이지 전환의 기본 메커니즘을 제공한다면, Transition은 그 전환을 더욱 부드럽고 사용자 친화적으로 만드는데 도와줌.
function Router() {
const [page, setPage] = useState('/');
const [isPending, startTransition] = useTransition();
function navigate(url) {
startTransition(() => {
setPage(url);
});
}
// ...
이유
- Transition은 낮은 우선순위 상태 업데이트(page 변경)이 진행중이더라도, 사용자 인터렉션에 즉시 반응 가능하므로.
- 즉...Transition으로 등록된 업데이트가 진행중일 때, 리액트는 이를 중단하고, 새로운 사용자 인터렉션을 먼저 처리가능하므로!
- 원하지 않는 로딩 폴백을 보여주지 않으므로
- 일반적으로 새로운 콘텐츠를 로드할 때, 로딩 스피너 등을 보여주는데,
- Transition을 사용하면, 새 콘텐츠가 준비될 때 까지 기존 콘텐츠를 계속 보여줄 수 있다.
import { Suspense, useState, useTransition } from 'react';
import IndexPage from './IndexPage.js';
import ArtistPage from './ArtistPage.js';
import Layout from './Layout.js';
export default function App() {
return (
<Suspense fallback={<BigSpinner />}>
<Router />
</Suspense>
);
}
function Router() {
const [page, setPage] = useState('/');
const [isPending, startTransition] = useTransition();
function navigate(url) {
startTransition(() => {
setPage(url);
});
}
let content;
if (page === '/') {
content = (
<IndexPage navigate={navigate} />
);
} else if (page === '/the-beatles') {
content = (
<ArtistPage
artist={{
id: 'the-beatles',
name: 'The Beatles',
}}
/>
);
}
return (
<Layout isPending={isPending}>
{content}
</Layout>
);
}
export default function Layout({ children, isPending }) {
return (
<div className="layout">
<section className="header" style={{
opacity: isPending ? 0.7 : 1
}}>
Music Browser
</section>
<main>
{children}
</main>
</div>
);
}
function BigSpinner() {
return <h2>🌀 Loading...</h2>;
}