Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suspense - hydration error on page refresh #1

Open
nemanjam opened this issue Jul 14, 2022 · 1 comment
Open

Suspense - hydration error on page refresh #1

nemanjam opened this issue Jul 14, 2022 · 1 comment

Comments

@nemanjam
Copy link
Owner

Describe the bug

In development mode on page refresh this error appears. It is related to this code in layouts/PageLayout/PageLayout.tsx:

Error: This Suspense boundary received an update before it finished hydrating. 
This caused the boundary to switch to client rendering. 
The usual way to fix this is to wrap the original update in startTransition.
const PageLayout: FC<Props> = ({ children, noPaddingTop = false }) => {
  const b = withBem('page-layout');

  return (
    <ErrorBoundaryWrapper errorFallbackType="screen">
      <SuspenseWrapper loaderType="screen">
        <MeProvider>
          <div className={b()}>
            <Navbar />
            <div className={b('navbar-placeholder')} />

            <main className={b('content', { 'no-padding-top': noPaddingTop })}>
              {/* Views (page) level loading and error handling */}
              <ErrorBoundaryWrapper errorFallbackType="page">
                <SuspenseWrapper loaderType="page">{children}</SuspenseWrapper>
              </ErrorBoundaryWrapper>
            </main>

            <Footer />
          </div>
        </MeProvider>
      </SuspenseWrapper>
    </ErrorBoundaryWrapper>
  );
};

It's related to logged in user being fetched between two Suspense boundaries, and that user object affects states in child components, causing difference on client and server. It is enough to remove inner Suspense boundary to prevent the error. Another way to prevent it is to render null in MeProvider when useMe is in loading state, but that causes entire UI to flicker.

This error is easy to reproduce when query keys mismatch in prefetchQuery in getServerSideProps and client side useQuery. But some other state mismatch between client and server also causes this error, I wasn't able to determine which state mismatch exactly.

Here is the link of test case repository for reproduction:

https://github.com/nemanjam/hydration-test-case

// my-react-query/posts/usePosts.ts
export const usePosts = () => {
  const query = useQuery<Post[], AxiosError>(['posts'], () => getPosts());
  return query;
};

// 2.
// pages/index.tsx
export const getServerSideProps: GetServerSideProps = async ({ req, res }) => {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery(['posts'], () => posts);
};

To Reproduce

Start app in development mode, login as any user, go to profile or home page and refresh it few times, this error will appear. In production build it doesn't seem to appear.

Expected behavior

Error should not appear on page refresh.

Screenshots

2022-07-14_09-06

Environment (please complete the following information):

  • Development or production app environment: development
  • Browser [e.g. chrome v60.12.0, safari 10.1]: both Chrome and Firefox
  • OS: [e.g. iOS, Windows x64] (if applicable): Ubuntu 20.04
  • node version (if applicable): v16.13.1

Additional context

Here is related issue in React repository but suggested solution to memoize children prop does not prevent error and just causes stale links in navbar.

facebook/react#24476 (comment)

@nemanjam
Copy link
Owner Author

nemanjam commented Jun 7, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant