Server-Side Rendering with React#
Helper functions#
These functions are meant to be used together, in different steps of your application.
prepareReactRender#
Function designed to be used before the React Render is being made, for example, in places like getStaticProps or getServerSideProps of Next.js
Internally it uses react-ssr-prepass
useHydrateCache#
Function designed to be placed at the very top of the hydrated component
Example#
Made with Next.js SSR Data Fetching in mind.
It's exactly the same usage for getServerSideProps
If you are using staleWhileRevalidate
in your application, You should always set 'shouldRefetch' as false, since that feature will always do the refetch anyways.
import { PropsWithServerCache } from '@gqty/react';
import { GetStaticProps } from 'next';
import { prepareReactRender, useHydrateCache, useQuery } from '../gqty';
type PageProps = PropsWithServerCache<{
name: string;
}>;
export default function ExamplePage({ cacheSnapshot, name }: PageProps) {
useHydrateCache({
cacheSnapshot,
// If it should refetch everything after the component is mounted
// By default 'shouldRefetch' is `false` (You can change it in the 'defaults' option)
shouldRefetch: false,
});
const query = useQuery();
return (
<div>
<p>{query.hello({ name })}</p>
</div>
);
}
export const getStaticProps: GetStaticProps<PageProps> = async (_ctx) => {
const name = 'John';
const { cacheSnapshot } = await prepareReactRender(
<ExamplePage name={name} />
);
return {
props: {
cacheSnapshot,
name,
},
};
};
Using Suspense#
Please check Suspense in SSR
Using Next.js Router#
If you are using Next.js useRouter
inside a component of a Next.js project, you might encounter errors like:
TypeError: Cannot destructure property 'pathname' of 'Object(...)(...)' as it is null.
Since with prepareReactRender
you are rendering outside of the Next.js tree, you don't have access to it's router
, and it's not even created yet.
We suggest a couple of solutions:
Add a default object before destructuring#
You will need to check if you really have any router property available
import { useRouter } from 'next/router';
// ...
const { pathname } = useRouter() || {};
// pathname == undefined while "prepareReactRender"
Mocking Router Data#
Here you can either manually set the values of the router, or simply let it be {}
, and all it's properties are simply going to be undefined.
import type { PropsWithServerCache } from '@gqty/react';
import type { GetServerSideProps } from 'next';
import { useHydrateCache, prepareReactRender } from '../gqty';
import { useRouter } from 'next/router';
import { RouterContext } from 'next/dist/next-server/lib/router-context';
export const getServerSideProps: GetServerSideProps<PropsWithServerCache> =
async ({}) => {
const { cacheSnapshot } = await prepareReactRender(
<RouterContext.Provider
value={
{
pathname: '/page',
} as any
}
>
<Page />
</RouterContext.Provider>
);
return {
props: {
cacheSnapshot,
},
};
};
export default function Page({ cacheSnapshot }: PropsWithServerCache) {
// ...
const {
// ...
} = useRouter();
// ...
}