skip to Main Content

I did everything according to the documentation, but there is no server rendering

I have created a page
app/layout.tsx

export default async function RootLayout({children}: {children: React.ReactNode}) {
  const queryClient = getQueryClient()
  const dehydratedState = dehydrate(queryClient)

  return (
    <html>
      <body>
          <Providers>
            <HydrationBoundary state={dehydratedState}>
               {children}
            </HydrationBoundary>
          </Providers>
      </body>
    </html>
  )
}

Providers

'use client'

import React, { useState } from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

function Providers({ children }: React.PropsWithChildren) {
  const [client] = useState(
    new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000 } } })
  )

  return (
    <QueryClientProvider client={client}>
       {children}
    </QueryClientProvider>
  )
}

export default Providers

Page

export default async function AdminUsersList() {
  const queryClient = getQueryClient()
  await queryClient.prefetchInfiniteQuery({
    queryKey: ['users'],
    queryFn: () => fetchUsers(0),
    initialPageParam: 0
  })

  return (
    <UserList />
  )
}

userlist

export default function UserList() {
  const {
    data: users,
    fetchNextPage,
    hasNextPage,
    isLoading,
    isError,
  } = useUsers()

  if (isLoading && !users) return <>loading...</>;

  return (
     <div>
      {!isLoading && users && (
        <InfiniteScroll
          pageStart={0}
          hasMore={!isError && hasNextPage}
          loader={<Preloader key='loader' />}
          loadMore={() => fetchNextPage({ cancelRefetch: false })}
        >
            <div>
              {users.pages.map((group, i) => (
                <React.Fragment key={i}>
                  {group.users.map((user) => (
                    {user.username}
                  ))}
                </React.Fragment>
              ))}
           </div>
        </InfiniteScroll>
      )}
    </div>
  )
}

getQueryClient

import { QueryClient } from "@tanstack/react-query"

const getQueryClient = () => new QueryClient()
export default getQueryClient

fetchUsers

import { Error } from '@/types/error'
import { User } from '@/types/entities/user'
import { useInfiniteQuery } from '@tanstack/react-query'

interface Response {
  users: User[],
  nextCursor: number
}

export async function fetchUsers(pageParam: unknown) {
  try {
    const res = await fetch(`http://localhost:3001/api/admin/users?skip=${!pageParam ? 0 : pageParam}`, { cache: 'no-store' });
    return await res.json()
  } catch (err: any) {
    throw err.response.data
  }
}

export default function useUsers() {
  return useInfiniteQuery<Response, Error>({
    queryKey: ['users'],
    queryFn: ({ pageParam }) => fetchUsers(pageParam),
    initialPageParam: 0,
    getNextPageParam: (lastPage) => lastPage.nextCursor,
  })
}

2

Answers


  1. Chosen as BEST ANSWER

    The problem was that. What should be done in each page like this

    export default async function AdminUsersList() {
      const queryClient = getQueryClient()
      await queryClient.prefetchInfiniteQuery({
        queryKey: ['users'],
        queryFn: () => fetchUsers(0),
        initialPageParam: 0
      })
    
      return (
        <HydrationBoundary state={dehydratedState}> // This
          <UserList />
        </HydrationBoundary>
      )
    }
    

    I just can't figure out why it doesn't pick it up from layout.


  2. Your code looks mostly correct. But I have a few suggestions,

    Wrap you components that rely on React Query data with Suspense and HydrationBoundary. Here is a sample code:

    import { Suspense } from 'react-query';
    import { HydrationBoundary } from 'react- 
    query/hydration';
    
    function RootLayout({ children }) {
      const queryClient = getQueryClient();
      const dehydratedState = dehydrate(queryClient);
    
      return (
        <html>
          <body>
            <Providers>
              <Suspense fallback={<div>Loading...</div>}>
                <HydrationBoundary state={dehydratedState}>
                  {children}
                </HydrationBoundary>
              </Suspense>
            </Providers>
          </body>
        </html>
      );
    }
    

    Thanks.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search