: 자식 컴포넌트가 로딩을 마칠 때까지 fallback을 보여주 컴포넌트
관련 내용 : Streaming SSR
<Suspense fallback={<Spinner />}>
<UserList />
</Suspense>
React는 자식 컴포넌트에서 필요한 모든 코드와 데이터가 로드될 때까지 loading fallback을 보여준다.
Suspense 내부의 전체 트리는 하나의 요소로 취급된다. 만약 Suspense 내부의 여러 컴포넌트가 존재하고, 그 중 하나가 데이터 패칭으로 인해 렌더링이 중단되고 있다면, Suspense 내부의 모든 컴포넌트가 로딩 표시를 보여줄 것이다.
만약 Suspense를 사용하지 않고 각 컴포넌트 마다 isLoading으로 로딩 화면에 대한 분기처리를 하면 먼저 데이터 패칭을 한 컴포넌트가 먼저 렌더링 될 것이고, 해당 컴포넌트가 사용자에게 먼저 보여질 것이다. 이는 마치 폭포수처럼 순차적으로 컴포넌트가 보여질 것이며, 사용자에게 오히려 좋지 않은 경험을 제공할 수 있다.
컴포넌트가 중단되면(즉, 로딩 상태라면) 자신을 감싼 가장 가까운 부모 Suspense컴포넌트가 동작한다. 이는 여러 로딩 순서를 만들어 중첩된 Suspense아키텍쳐를 만들 수 있다는 것을 의미한다. 각 Suspense 경계의 fallback은 다음 단계의 컨텐츠가 이용 가능하게 되면 채워질 것이다.
새로운 데이터 로딩을 마치기 전까지 오래된 데이터를 보여줄 수 있다.
useDeferredValue를 이용하여 기존의 데이터를 보여줄 수 있다.
<aside> 💡 useDeferredValue?
: UI의 일부 업데이트를 연기할 수 있는 훅이다.
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// ...
}
새로운 데이터를 패칭하는 동안 오래된 데이터를 보여줄 수 있다.
컨텐츠가 오래되었음을 보여줄 수 있다.
<div style={{
opacity: query !== deferredQuery ? 0.5 : 1,
}}>
<SearchResults query={deferredQuery} />
</div>
UI에 대해 리렌더링을 연기한다. </aside>
선언적으로 코드를 작성할 수 있다.
if문으로 분기처리를 하여 ‘로딩’을 보여준다는 점에서 명령형 프로그래밍 기법에 더 가깝다. React에서 추구하는 선언형 프로그래밍에 더 가깝게 작성할 수 있다.
관심사를 분리할 수 있다.
데이터를 패칭하는 컴포넌트에서는, 데이터를 패칭하는 로직과 이 데이터를 직접 보여주거나, 혹은 컴포넌트에 넘겨주는 로직만 작성하면 된다. 로딩과 에러에 대한 로직을 이 컴포넌트의 바깥으로 뺼 수 있다.
Suspense가 궁극적으로 해결하고자 한 것은 바로 Streaming SSR이다.
SSR은 애플리케이션에서 상호작용이 필요없는 부분을 더 이른 시기에 볼 수 있게 해주어 유저들로 하여금 Javascript가 로드되는 동안 정적 컨텐츠를 볼 수 있도록 해준다.
하지만 이 SSR은 무언가 보여주기 전까지 워터폴 방식으로 모든 것을 다 가져와야 한다는 단점이 있다. 서버에서 데이터 가져오기 → 서버에서 HTML로 렌더링 → 코드 불러오기 → Hydrate순서대로 수행해야 한다. 이 중 어떤 단계도 이전 단계가 전체 애플리케이션에 대하여 끝나기 전까지 시작하지 못한다는 단점이 있다.