SSG not pre-fetching data

So I am following the twitter clone video. The profile page is created entirely through static site generation. I really want to understand SSG in general, so why is it that when I try to access the profile page, the Errorpage with the 404 flashes for one second before showing the actual content ? I understant that this is the fallback page which should only show when there is for example no user. Moreover because we use SSG, the user is basically null for a split second. Even in the video and the final code when you refresh the page anywhere you can very briefly see the "Log in" button before the app knows that a user is signed in. But the content of the profile page should be pre-fetched with the ssgHelper. I can't understand why my code shows the errorpage before showing the profile page content. If anyone could help me or at least explain how SSG works, I would really appreciate it.
1 Reply
compil3
compil314mo ago
Here is my code:
import type {
GetStaticPaths,
GetStaticPropsContext,
InferGetStaticPropsType,
NextPage,
} from "next";
import Head from "next/head";
import React from "react";
import { ssgHelper } from "~/server/api/ssgHelper";
import { api } from "~/utils/api";
import ErrorPage from "next/error";

const ProfilePage: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
id,
}) => {
const { data: profile } = api.profile.getById.useQuery({ id });

if (profile == null) {
return <ErrorPage statusCode={404} />;
}

return (
<>
<Head>
<title>{`Twitter Clone - ${profile.name}`}</title>
</Head>
{profile.name} // instead of showing this content, The Errorpage flashes for 1 second, before showing the content
</>
);
};

export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [],
fallback: "blocking",
};
};

export async function getStaticProps(
context: GetStaticPropsContext<{ id: string }>,
) {
const id = context.params?.id;

if (id == null) {
return {
redirect: {
destination: "/",
},
};
}

const ssg = ssgHelper();
await ssg.profile.getById.prefetch({ id });

return {
props: {
trpcState: ssg.dehydrate(),
id,
},
};
}

export default ProfilePage;
import type {
GetStaticPaths,
GetStaticPropsContext,
InferGetStaticPropsType,
NextPage,
} from "next";
import Head from "next/head";
import React from "react";
import { ssgHelper } from "~/server/api/ssgHelper";
import { api } from "~/utils/api";
import ErrorPage from "next/error";

const ProfilePage: NextPage<InferGetStaticPropsType<typeof getStaticProps>> = ({
id,
}) => {
const { data: profile } = api.profile.getById.useQuery({ id });

if (profile == null) {
return <ErrorPage statusCode={404} />;
}

return (
<>
<Head>
<title>{`Twitter Clone - ${profile.name}`}</title>
</Head>
{profile.name} // instead of showing this content, The Errorpage flashes for 1 second, before showing the content
</>
);
};

export const getStaticPaths: GetStaticPaths = () => {
return {
paths: [],
fallback: "blocking",
};
};

export async function getStaticProps(
context: GetStaticPropsContext<{ id: string }>,
) {
const id = context.params?.id;

if (id == null) {
return {
redirect: {
destination: "/",
},
};
}

const ssg = ssgHelper();
await ssg.profile.getById.prefetch({ id });

return {
props: {
trpcState: ssg.dehydrate(),
id,
},
};
}

export default ProfilePage;
import { createServerSideHelpers } from "@trpc/react-query/server";
import { appRouter } from "./root";
import superjson from "superjson";
import { createInnerTRPCContext } from "./trpc";

export function ssgHelper() {
return createServerSideHelpers({
router: appRouter,
ctx: createInnerTRPCContext({ session: null }),
transformer: superjson,
});
}
import { createServerSideHelpers } from "@trpc/react-query/server";
import { appRouter } from "./root";
import superjson from "superjson";
import { createInnerTRPCContext } from "./trpc";

export function ssgHelper() {
return createServerSideHelpers({
router: appRouter,
ctx: createInnerTRPCContext({ session: null }),
transformer: superjson,
});
}
import { z } from "zod";

import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";

export const profileRouter = createTRPCRouter({
getById: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input: { id }, ctx }) => {
const currentUserId = ctx.session?.user.id;
const profile = await ctx.db.user.findUnique({
where: { id },
select: {
name: true,
image: true,
_count: {
select: { followers: true, follows: true, tweets: true },
},
followers:
currentUserId == null
? undefined
: { where: { id: currentUserId } },
},
});

if (profile == null) return;

return {
name: profile.name,
image: profile.image,
followersCount: profile._count.followers,
followsCount: profile._count.follows,
tweetsCount: profile._count.tweets,
isFollowing: profile.followers.length > 0,
};
}),
});
import { z } from "zod";

import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";

export const profileRouter = createTRPCRouter({
getById: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input: { id }, ctx }) => {
const currentUserId = ctx.session?.user.id;
const profile = await ctx.db.user.findUnique({
where: { id },
select: {
name: true,
image: true,
_count: {
select: { followers: true, follows: true, tweets: true },
},
followers:
currentUserId == null
? undefined
: { where: { id: currentUserId } },
},
});

if (profile == null) return;

return {
name: profile.name,
image: profile.image,
followersCount: profile._count.followers,
followsCount: profile._count.follows,
tweetsCount: profile._count.tweets,
isFollowing: profile.followers.length > 0,
};
}),
});
nevermind I found the issue. it was some typescript error. I had to do profile.followers?.length
Want results from more Discord servers?
Add your server