-
[React] Suspense구버전/React 2023. 11. 22. 15:42
개요
- Suspense의 개념 및 동작방식
- Usages
Suspense
React에서 무언가를 기다릴 때 사용한다. (children이 로딩되기 전에 fallback을 보여준다)
useEffect의 단점)
- UI폭포(Waterfall)를 발생한다(상위 컴포넌트의 데이터부터 UI가 순차적으로 나타나는 것)
- 초기랜더링 이후 발생하는 사이드 이펙트로, 데이터 로딩이 끝나면 리랜더링을 수행하기에 Race Condition에 취약
이러한 단점을 보완해주는 Suspense
예시)
<Suspense fallback={<Loading />}> <SomeComponent /> </Suspense>
fallback에는 실제 UI가 로딩이 끝날 때까지 대신 보여줄 컴포넌트를 넣어준다 (스피너, 스켈레톤...)
컨텐츠를 보여준 후 다시 suspend상태에 들어가게 되면 다시 fallback을 보여준다.
동작방식)
<Layout> <NavBar /> <Sidebar /> <RightPanel> <Post /> <Suspense fallback={<Spinner />}> <Comments /> </Suspense> </RightPane;> </Layout>
위와 같은 구조의 트리에서 Comments에 대해 Suspense를 적용했을 때입니다.
Comment가 suspend일떄와 완료되었을 때 - Comments를 제외한 나머지 컴포넌트를 먼저 받아옵니다. 이는 클라이언트가 처음 받는 HTML에는 Comments가 아닌 스피너로 대체 된 HTML을 받는다는 것을 의미합니다.
- 데이터가 준비되었다면 React는 같은 스트림으로 추가적인 HTML을 보내어 Suspned된 컴포넌트가 들어갈 자리에 새로운 컴포넌트를 갈아끼우는 코드가 들어갑니다.
- 아직 Hydration을 거치지 않아 유저 인터렉션을 수행할 수 없는 상태에입니다. (기존 SSR과 달리 Suspense를 통해서 컴포넌트 단위의 Hydration이 가능하게 됨)
여러개의 Suspense를 사용했을 때 React는 어떻게 행동할까?
<Layout> <NavBar /> <Suspense fallback={<Spinner />}> <Sidebar /> </Suspense> <RightPane> <Post /> <Suspense fallback={<Spinner />}> <Comments /> </Suspense> </RightPane> </Layout>
Suspense가 두개 있기 때문에 Hydration도 각기 일어나게 됩니다.
- Suspense이외의 나머지 컴포넌트는 HTML랜더링과 Hydration이 일어나게 된다
- 이후 먼저 찾아지는 Suspense 바운더리가 Hydration을 실행한다.
- 이때 Hydration이 진행되는 컴포넌트가 아닌 다른 컴포넌트가 유저 인터렉션을 받게 된다면?
- React는 클릭 이벤트가 발생한 컴포넌트를 먼저 동기적으로 Hydrating한다.
Usages
가장 기본적 예시
<Suspense fallback={<Loading />}> <Albums /> </Suspense>
주의사항)
- Suspense의 children에서 데이터를 이벤트핸들러나 useEffect로 가져온다면 Suspense는 감지하지 못한다
- Next.js와 같은 프레임워크에서 자주 사용되고 React만 사용한다면 큰 의미가 없다
컨텐츠 여러 개를 동시에 보여주고 싶을 때 (promiseAll 같은 느낌)
<Suspense fallback={<Loading />}> <Biography /> <Panel> <Albums /> </Panel> </Suspense>
각 컨텐츠의 타이밍이 다를 때
<Suspense fallback={<BigSpinner />}> <Biography /> <Suspense fallback={<AlbumsGlimmer />}> <Panel> <Albums /> </Panel> </Suspense> </Suspense>
- Biography 컴포넌트는 Albums 컴포넌트가 로딩되기를 기다리지 않아도 된다.
- 한번에 보여줄지, 특정 단위별로 보여줄지 결정할 수 있다.
데이터가 불러와지는 동안 이전의 데이터를 보여주고 싶다면?
import {useDeferredValue} from 'react' const deferredQuery = useDeferredValue(query); ... <Suspense fallback={<h2>Loading...</h2>}> <SearchResults query={deferredQuery} /> </Suspense>
- 이전 결과값을 유지하여 보여줄 수 있는 방법
참고자료 : 블로그1
'구버전 > React' 카테고리의 다른 글
[React] react-hook-form (Basic) (0) 2023.12.08 [React] 새로운 리액트 문서에서 제시하는 9가지 권장 사항 (1) 2023.12.06 [Hooks] useEffect (1) 2023.11.22 [Article] React 렌더링 동작에 대한 (거의) 완벽한 가이드(1편) (0) 2023.11.21 [SWR] Data의 reavalidate, mutate 활용 (0) 2023.11.03