-
[React] Suspense에 대해 알아보자카테고리 없음 2023. 8. 7. 21:56728x90
이 글은 React 공식문서를 보며 공부한 내용을 정리한 글입니다.₩
Suspense
suspense는 로딩이 완료되기 전까지 fallback을 보여주는 장치이다.
<Suspense fallback={<Loading />}> <SomeComponent /> </Suspense>Props
suspense는 children으로 렌더링 하려는 자식 요소를 받는다. 만약 자식 요소의 렌더링이 완료되지 않았다면 대체 콘텐츠를 렌더링 하는 상태로 전환된다.
suspense는 fallback prop으로 실제 UI가 완전히 로드되지 않았을 때에 대신 렌더링할 대체 UI를 받는다.
모든 React Node가 허용되지만 실제로는 로딩 스피너와 스켈레톤과 같은 가벼운 요소가 사용된다.
- 스피너

- 스켈레톤

스켈레톤이 무엇인지 모르겠어서 찾아보았는데 흔히 유튜브에서 볼 수 있었다.
주의사항
- React는 처음으로 마운트되기 전에 일시 중단된 렌더링에 대한 상태를 보존하지 않는다. 컴포넌트가 로드되면 React는 일시 중단된 트리를 처음부터 다시 렌더링 시도한다.
- 만약 suspense가 트리 내용을 보여주다가 일시 중단되면 그전에 보여주었던 콘텐츠가 다시 나타난다. startTransition이나 useDeferredValue에 의해서가 아닐 경우에 말이다.
- React가 이미 보이는 내용을 숨겨야하는 상황에서 일시 중지되면 그 내용에 적용된 layout Effects를 정리한다. 그리고 내용이 보여야 할 때에 다시 layout Effects를 실행시킨다.
- React에는 suspense와 통합된 내부 최적화가 포함되어있다.
용법
로드되는 동안 대체 표시
<Suspense fallback={<Loading />}> <Albums /> </Suspense>suspense로 애플리케이션의 모든 부분을 감쌀 수 있다. 하위 컴포넌트가 모두 렌더링 될 때까지 Loading fallback을 표시한다. 데이터가 로드되면 fallback을 숨기고 하위 컴포넌트를 보여준다.
- suspense가 활성화되는 것은 suspense를 지원하는 데이터 소스에만 해당된다.
콘텐츠를 한 번에 공개
기본적으로 suspense내의 전체 트리는 단일 단위로 처리된다. 때문에 하위 컴포넌트 중 일부만 렌더링 되지 않아도 모두 함께 fallback으로 대체된다.
그런 다음 모두 함께 렌더링 준비가 되면 한 번에 렌더링 시킨다.
데이터를 불러오는 컴포넌트는 suspense의 직접적인 자식일 필요는 없다.
로드될 때 중첩된 콘텐츠 표시
컴포넌트의 렌더링이 일시 중단된다면 가장 가까운 상위 suspense의 fallback을 표시한다.
이를 통해 여러 개의 suspense를 중첩하여 로딩 순서를 관리할 수 있다.
<Suspense fallback={<BigSpinner />}> <Biography /> <Suspense fallback={<AlbumsGlimmer />}> <Panel> <Albums /> </Panel> </Suspense> </Suspense>위 코드의 순서는 이러하다.
- Biography가 로드되지 않은 경우 BigSpinner 보여주기
- Biography로드가 완료되면 표시
- Albums가 로드되지 않으면 AlbumsGlimmer표시
- Albums가 로드되면 Albums 표시
- suspense 경계는 사용자가 UI를 경험하기 원하는 순간보다 더 세분화되면 안 된다. 디자이너와 로드 상태 배치에 관련하여 대화를 하자. 이미 디자인 와이어프레임에 로드 상태가 배치되었을 가능성이 높다.
새로운 콘텐츠가 로드되는 동안 오래된 콘텐츠 표시
아래 코드에서는 검색 결과를 가져오는 동안 SearchResults 컴포넌트가 일시 중단된다. a를 입력한 후에 ab를 입력하면 a에 대한 검색 결과가 대체 콘텐츠로 표시된다.
<> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <SearchResults query={query} /> </Suspense> </>일반적인 UI 대안 패턴은 업데이트를 연기하고 새 결과가 준비될 때까지 이전 결과를 계속해서 표시하는 것이다. useDeferredValue훅으로 쿼리의 연기된 버전을 전달할 수 있다.
deferredQuery는 데이터가 로드될 때까지 이전 값을 유지하기 때문에 잠시 동안 SearchResults에 오래된 결과가 표시된다.
const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); const isStale = query !== deferredQuery; return ( <> <label> Search albums: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Loading...</h2>}> <div style={{ opacity: isStale ? 0.5 : 1 }}> <SearchResults query={deferredQuery} /> </div> </Suspense> </> );이미 공개된 콘텐츠가 숨겨지는 것을 방지
컴포넌트가 일시 중단되면 상위 suspense가 fallback을 표시한다. 이로 인해 이미 일부 콘텐츠를 표시하고 있는 사용자 경험이 왜곡될 수 있다.
startTransition을 이용하여 이를 개선할 수 있다.
const [page, setPage] = useState('/'); function navigate(url) { startTransition(() => { setPage(url); }); }이는 상태 전환이 긴급하지 않으며 이미 공개된 콘텐츠를 숨기는 대신 이전 페이지를 계속 표시하도록 한다.
전환 상태임을 나타낸다
페이지 전환이 일어나는 동안 style 변경을 줄 수 있다.
내비게이션시 suspense경계 재설정
전환하는 동안 React는 이미 공개된 콘텐츠를 숨기지 않는다. 하지만 다른 매개변수를 가지는 경로로 이동할 경우 React에게 다른 콘텐츠임을 알리고 싶을 수 있다. 이때 key를 사용한다.
<ProfilePage key={queryParams.id} />업데이트 중 UI가 fallback으로 대체되지 않게 하려는 경우
이를 방지하려면 startTransition을 사용해서 긴급하지 않은 업데이트로 표시한다.
function handleNextPageClick() { // If this update suspends, don't hide the already displayed content startTransition(() => { setCurrentPage(currentPage + 1); }); }이렇게 하면 기존 콘텐츠가 숨겨지는 것을 방지할 수 있다. suspense는 로딩이 완료되기 전까지 fallback을 보여주는 장치이다.
<Suspense fallback={<Loading />}> <SomeComponent /> </Suspense>Contribute in esperer
728x90