I am using an Urql client to make a query to my graphql server. My query looks like this:
const username = () => {
const { t: translation } = useTranslation(["common", "profile"]);
const { query, locale } = useRouter();
const username = query.username;
const [{ data: userProfileData }] = useUserProfileQuery({
variables: {
username: username as string,
},
pause: isServer || !username,
});
const userProfile = userProfileData?.userProfile;
return (
<Text>{userProfile.name}</Text>
);
};
export default withUrqlClient(createUrqlClient, { ssr: false })(username);
This would be fine, but because I am using the next-i18next
library to localise my website, I have to add the getServerSideProps
function.
export const getServerSideProps = async ({ locale, locales}: any) => {
return {
props: {
...(await serverSideTranslations(
locale,
["common", "profile", "settings"],
null,
locales
)),
},
};
};
This all works fine, but it means I can't server-side render my page by setting ssr to true like the following:
export default withUrqlClient(createUrqlClient, { ssr: false })(username);
My goal is to make the query on the useUserProfileQuery
server.
I read the following guide: https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#ssr-with-getstaticprops-or-getserversideprops
. Which suggested that I do the query in getServerSideProps
. As a result, the new getServerSideProps
function looks like this:
export const getServerSideProps = async ({ locale, locales, query }: any) => {
const ssrCache = ssrExchange({ isClient: false });
const client = initUrqlClient(createUrqlClient(ssrCache), false);
if (client)
await client
.query(UserProfileDocument, {
username: query.username,
})
.toPromise();
return {
props: {
...(await serverSideTranslations(
locale,
["common", "profile", "settings"],
null,
locales
)),
urqlState: ssrCache.extractData(),
},
};
};
But, I get the following error:
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Warning: Expected server HTML to contain a matching <div> in <div>.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
What am I doing wrong? Please help.
The solution is to return userProfile
in getServerProps
and remove the query from the username
function.
Here's what the new getServerProps
looks like
export const getServerSideProps: GetServerSideProps = async ({
locale,
locales,
query,
}: any) => {
const ssrCache = ssrExchange({ isClient: false });
const client = initUrqlClient(createUrqlClient(ssrCache), false);
let userProfile = null;
if (client)
userProfile = await client
.query(UserProfileDocument, {
username: query.username,
})
.toPromise();
return {
props: {
...(await serverSideTranslations(
locale,
["common", "profile", "settings"],
null,
locales
)),
userProfile: JSON.parse(JSON.stringify(userProfile?.data?.userProfile)),
},
};
};
This is what the new username
function looks like
const username = ({locale, userProfile}: any) => {
const { t: translation } = useTranslation(["common", "profile"]);
return (
<Text>{userProfile.name}</Text>
);
};
export default withUrqlClient(createUrqlClient, { ssr: false })(username);