## Problem: How to keep server state and client state in sync while following good practicies. I'm having three files in this example: ## Navbar (server-side) This fetches the user server side and displays the menu depending if someone is logged in or not. It's also fetching userData which is dependent on user so it awaits the user fetch and then fetches userData. ```js export default async function Navbar({ lang }: NavbarProps) { const supabase = createClient(); const queryClient = new QueryClient(); const user = await queryClient.fetchQuery({ queryKey: ["user"], queryFn: () => getUserServer(supabase), }); const cookieHeader = cookies().toString(); const userData = await queryClient.fetchQuery({ queryKey: ["userData", user?.id], queryFn: () => fetchUserDataServer(cookieHeader), }); ``` ## LoggedInHome (server-side) This fetches the user server side to redirect if a user is not logged in. ```js export default async function LoggedInHomePage({ params: { lang }, }: LoggedInHomePageProps) { const supabase = createClient(); const queryClient = new QueryClient(); const user = await queryClient.fetchQuery({ queryKey: ["user"], queryFn: () => getUserServer(supabase), }); if (!user) { redirect(SIGN_IN); } await queryClient.prefetchQuery({ queryKey: ["profile"], queryFn: () => fetchProfile(supabase), }); ``` ## Affix (client-side) An component which shows credits of a user that frequently updates but uses the user and userData. The data is currently received by the server and updated on the client if the user is prefetched. ```js const TrailAffix: React.FC = () => { // useQuery hook const { data: user, isLoading: isUserLoading, error: userError, } = useGetUser(); // dependent useQuery hook const { data, isError: isUserDataError, isFetching, } = useGetUserData({ userId: user?.id, }); ``` Before I was using `await queryClient.prefetchQuery({` but now as I have state on the server that is not only passing it to the client component but also uses it, I'm worried that the server-side state can becomes out of sync. As you can see the state is on both server and server side. I'm not sure how to avoid refetches and make sure everything is only fetches once when loading the page but also in a fresh state when i update the states. **Just in case the question pops up I've set up a global query client.** ```js function makeQueryClient() { return new QueryClient({ defaultOptions: { queries: { // With SSR, we usually want to set some default staleTime // above 0 to avoid refetching immediately on the client staleTime: 60 * 1000, }, }, }); } let browserQueryClient: QueryClient | undefined = undefined; function getQueryClient() { if (isServer) { // Server: always make a new query client return makeQueryClient(); } else { // Browser: make a new query client if we don't already have one // This is very important, so we don't re-make a new client if React // suspends during the initial render. This may not be needed if we // have a suspense boundary BELOW the creation of the query client if (!browserQueryClient) browserQueryClient = makeQueryClient(); return browserQueryClient; } } export default function Providers({ children }: { children: React.ReactNode }) { const queryClient = getQueryClient(); return ( {children} ); } ``` I tried so many different strategies but just get more confused. I tried to uplift the state from Navbar.tsx useQuery fetches to the layout.tsx file but then layout.tsx and Navbar.tsx are fetching userData on the server and it just fetches even one more time as Navbar seems to not reseive the data from layout.tsx. So here another test I did. ```ts export default async function NavbarLayout({ children, params: { lang }, }: { children: React.ReactNode; params: { lang: AvailableLanguagesLowercase }; }) { const supabase = createClient(); const queryClient = new QueryClient(); const user = await queryClient.fetchQuery({ queryKey: ["user"], queryFn: () => getUserServer(supabase), }); const cookieHeader = cookies().toString(); await queryClient.prefetchQuery({ queryKey: ["userData", user?.id], queryFn: () => fetchUserDataServer(cookieHeader, "userData - Layout"), }); return ( <> {children} // This would be where Logged in Home is loaded as a child ); } ``` ## Stack: Next.js 15 App Router Tanstack Query 5