React Suspense works but only partially

138 views Asked by At

I am having a problem with Suspense in React JS.

Pictures speak a thousand words:

First State

Second State, Suspense fallback gets cleared

Third State, finally - Component loaded

The App renders Suspense Skeleton (first image), but it clears everything before rendering the components (second, then third image).

<div className="container">
      <Suspense fallback={<CarouselSkeleton />}>
        <Carousel action={latestAction} />
      </Suspense>
...

I am loading the Carousel component with a lazy(...) loader.

I did try to place Suspense on several outer layers, same behavior.

I was expecting component to be shown right after Suspense fallback, I am trying to improve CLS.

1

There are 1 answers

1
Jung hyeonuk On BEST ANSWER

The problem you're facing is probabably caused by fallbackData you'd given to your data fetching library like swr and tanstack-query, is used not only in initial rendering but also in afterwards re-rendering.

Your goal probabably is to give fallbackData for serverside rendering and make it suspended for every rerendering in client side. But the problem is that fallbackData is internally used for fallbackData when there's data revalidating if the key changes, so that every rerendering after initial rendering makes unexpected layout shift. (prevData -> fallbackData -> newData).

What you have to do is disable fallbackData after initial rendering.

To do so, you can do like this.

  const hasMounted = useRef(false);

  // assume you use SWR
  const { data, isLoading, isValidating } = useSWR(
  queryString,
  {
    suspense: true,
    fallbackData: hasMounted.current ? undefined : fallbackData,
  }
  );

  useEffect(() => {
    hasMounted.current = true;
  }, []);

by using useRef and useEffect, you can set fallbackData to undefined.