T
TanStack•2y ago
rare-sapphire

What is best way to compose queryFn options for server and client in SSR

Just want to know what pattern you guys follow for queryOptions that will work and client and server while preloading. For example If I am preloading query on server it should call database directly and on client it should fallback to api route
3 Replies
eastern-cyan
eastern-cyan•17mo ago
interesting problem 😁
// serverFetch.js
export const serverFetch = async (queryKey) => {
// Directly fetch data from the database on the server
const data = await db.query(...);
return data;
};

// clientFetch.js
export const clientFetch = async (queryKey) => {
// Fetch data from the API route on the client
const response = await fetch(`/api/${queryKey}`);
const data = await response.json();
return data;
};
// serverFetch.js
export const serverFetch = async (queryKey) => {
// Directly fetch data from the database on the server
const data = await db.query(...);
return data;
};

// clientFetch.js
export const clientFetch = async (queryKey) => {
// Fetch data from the API route on the client
const response = await fetch(`/api/${queryKey}`);
const data = await response.json();
return data;
};
// fetchData.js
import { serverFetch } from './serverFetch';
import { clientFetch } from './clientFetch';

export const fetchData = (queryKey) => {
if (typeof window === 'undefined') {
// Server-side fetching
return serverFetch(queryKey);
} else {
// Client-side fetching
return clientFetch(queryKey);
}
};
// fetchData.js
import { serverFetch } from './serverFetch';
import { clientFetch } from './clientFetch';

export const fetchData = (queryKey) => {
if (typeof window === 'undefined') {
// Server-side fetching
return serverFetch(queryKey);
} else {
// Client-side fetching
return clientFetch(queryKey);
}
};
// component.js
import { useQuery } from '@tanstack/react-query';
import { fetchData } from './fetchData';

const MyComponent = () => {
const { data, isLoading, error } = useQuery(['myData'], fetchData);

// Render your component based on the query state
// ...
};

export default MyComponent;
// component.js
import { useQuery } from '@tanstack/react-query';
import { fetchData } from './fetchData';

const MyComponent = () => {
const { data, isLoading, error } = useQuery(['myData'], fetchData);

// Render your component based on the query state
// ...
};

export default MyComponent;
// pages/myPage.js
import { dehydrate } from '@tanstack/react-query';
import { fetchData } from './fetchData';

export async function getServerSideProps() {
const queryClient = new QueryClient();

await queryClient.prefetchQuery(['myData'], fetchData);

return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}

// Render your page component
// ...
// pages/myPage.js
import { dehydrate } from '@tanstack/react-query';
import { fetchData } from './fetchData';

export async function getServerSideProps() {
const queryClient = new QueryClient();

await queryClient.prefetchQuery(['myData'], fetchData);

return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
}

// Render your page component
// ...
you need to dehydrate when returning from the server, by dehydrating the state on the server and hydrating it on the client, you avoid the need to refetch the same data again on the client-side :thumbs_Up: since itll be transferred to theclient cache
rare-sapphire
rare-sapphireOP•17mo ago
I wonder if bundler will eliminate server related modules in client bundle using this approach
eastern-cyan
eastern-cyan•17mo ago
if ure using app router this wont work get server side props ..

Did you find this page helpful?