개발자
200ms 동안은 이전 UI를 보여주고, 그 다음부터는 skeleton ui를 보여주고 싶습니다. 하지만, 현재상황은 이렇습니다. useSuspenseQuery를 이용했을때, 처음 200ms동안 데이터가 없어서 높이가 0이 되었다가 다시 높아지면서 화면이 덜그럭거리는 문제가 있습니다. 그래서 useTransition을 이용해서 이전 UI상태를 유지하도록 했지만 지연시간이 길어졌을때는 skeleton ui가 보이질 않습니다. 제가 궁금한건 다음과 같습니다. 1. 보통 useSuspensequery를 사용해 skeleton ui를 보여줄때 초기 렌더링시 이전 데이터가 보이지 않아서 화면이 깜빡이는 문제를 어떻게 해결하나요? 2. useTransition과 skeleton ui는 같이 사용할 수 없는 건가요? 대략적인 코드는 다음과 같습니다. 각각 최상위 부모인 Search 페이지, 데이터를 불러오고 카드리스트를 업데이트하는 CardList 컴포넌트, 스켈레톤 UI의 지연을 처리하는 DeferredComponent 입니다.
답변 3
인기 답변
1번 질문에 대해서 생각해 본 부분을 남겨볼게요. 초기 렌더링 시 데이터가 없어서 영역 높이가 0이라 화면이 깜빡인다고 말씀하시는 걸까요? 그렇다면 렌더링할 컴포넌트에 최소한의 height를 지정해 놓으면 덜 깜빡거리게 느껴지지 않을까요? 그러나 여전히 깜빡임은 있을 것 같습니다. 캐시 데이터가 없는데 아직 isLoading이 true가 되지 않아 fallback으로 넘긴 skeleton ui가 맨 처음에 보이지 않는 문제라면 query data가 없는 경우에도 skeleton ui를 보여주도록 예외처리를 추가해 볼 수 있을 것 같습니다. 2번 질문에 대해서는 이미 캐시 데이터가 있는 경우에는 스켈레톤 ui를 보여주기 보단 keepPreviousdata 속성을 이용해서 이전 데이터를 보여주다가 새 데이터 응답이 완료되면 레이아웃 변경 없이 변경된 데이터만 보여주는 게 더 좋은 사용성이 아닐까 싶은 생각이 들었습니다. 질문자님이 하신 고민의 시간과 노력에 비해 떠오르는 생각으로 답변을 달다 보니 원하시는 답이 아닐 수 있을 것 같아요~ 참고만 해주시면 좋을 것 같습니다 :) 파이팅!!
previousData는 새로 페칭된 데이터로 갈음되기 전까지 유효합니다. 시간 의존성이 응답 시간에 달려있습니다. DeferredComponent의 시간 의존성은 컴포넌트 내부에 정의해 둔 delay에 달려있습니다. 둘 사이에는 관계성이 없습니다. A가 끝나고 B가 시작되고 B가 끝나고 C가 시작되는 식의 waterfall은 전후 종속성이 있거나 같은 의존성을 가져야 제어할 수 있습니다. 1,2 모두 이 의존성을 관리하는 문제로 보이네요.
같은 고민으로 덜컥거리는 것을 방지하기 위해 FadeIn이라는 컴포넌트를 Suspensive에서 제공하고 있는데 이걸 사용해보시면 어때요? https://github.com/toss/suspensive/blob/9127cecfb48e17ef7c53dabf29c991d86fb176df/examples/visualization/src/app/react-dom/FadeIn/page.tsx#L42 그럼 결과물은 이렇게 나오게 되어요 https://visualization.suspensive.org/react-dom/FadeIn
익명
작성자
2024년 12월 12일
오 토스에서 이런 라이브러리를 제공해주고 있었군요.. 감사합니다!!
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 10월 12일
React Suspense는 컴포넌트가 준비되지 않은 비동기 작업의 상태를 관리하기 위해 설계되었습니다. 초기 렌더링 시 발생하는 레이아웃의 변경이나 화면의 깜빡임과 같은 문제를 해결하는 방법에 대해 자세히 설명드리겠습니다. 1. 보통 useSuspenseQuery와 Skeleton UI를 사용할 때, 초기 렌더링 시 화면이 깜빡이는 문제를 해결하는 방법은 'SuspenseList'를 사용하는 것입니다. 이 기능을 사용하면 여러개의 컴포넌트가 로드 되는 순서를 정하거나, 모든 컴포넌트가 로드될 때까지 기다릴 수 있습니다. 깜빡임 문제는 대부분 데이터가 동시에 로드되지 않아서 생기므로, SuspenseList를 통해 데이터 로드 순서를 관리하거나 모든 데이터가 다 로드될 때까지 기다려 깜빡임 현상을 최소화할 수 있습니다. 2. useTransition과 Skeleton UI는 함께 사용할 수 있습니다. transition config에서 timeoutMs 설정값을 조절하여 transition 지속 시간을 정할 수 있습니다. 해당 시간 동안은 이전 UI 상태가 유지되며, 해당 시간 후 새로운 UI로 업데이트됩니다. 하지만 문제는 useTransition이 Suspense fallback에 대해서는 delay가 적용되지 않는다는 점입니다. React team도 이 점을 인지하고 있으나 아직까지 공식적인 해결책을 제시하지 않았습니다. 이러한 깜박임 현상은 실험적인 기능인 Concurrent mode와 함께 React.Suspense를 사용하면 개선할 수 있는 가능성이 큽니다. Concurrent mode를 사용하면, 로딩 중인 컴포넌트가 Main thread를 블로킹하지 않고 화면에 로딩 상태를 더 원활하게 표현할 수 있습니다. 현재 하위 호환성 및 안정성 문제로 아직 production에서 사용하기 어려운 단계이지만, kotlinx.coroutines.experimental 기능들과 같은 비동기 작업을 세밀하게 통제할 수 있는 API 제공을 목표로 하고 있습니다. 아래 코드는 `SuspenseList`와 `useTransition` 그리고 `React.Suspense`를 사용하는 간단한 예시입니다. ``` const [startTransition, isPending] = useTransition({ timeoutMs: 2000, }); <SuspenseList revealOrder="forwards" tail="hidden"> {posts.map(post => ( <Suspense key={post.id} fallback={<CardSkeleton />}> <Post post={post} /> </Suspense> ))} </SuspenseList> ``` 위에 방법들이 도움되길 바라며, 아직까지는 React Suspense와 관련된 여러가지 이슈들이 있고 이에 대한 최적의 해결책은 현재 개발 중인 Concurrent Mode에서 찾을 수 있을 것으로 기대하고 있습니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!