Skip to content

Commit f8f4ae6

Browse files
committed
Add prefetch for first questions list page
Signed-off-by: SeeuSim <[email protected]>
1 parent a428854 commit f8f4ae6

File tree

5 files changed

+47
-14
lines changed

5 files changed

+47
-14
lines changed

frontend/src/lib/router.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import { RouteGuard, loader as routeGuardLoader } from '@/components/blocks/rout
77
import { ForgotPassword } from '@/routes/forgot-password';
88
import { Login } from '@/routes/login';
99
import { QuestionDetails, loader as questionDetailsLoader } from '@/routes/questions/details';
10+
import { Questions, loader as questionsLoader } from '@/routes/questions/main';
1011
import { SignUp } from '@/routes/signup';
1112

1213
import { queryClient } from './query-client';
1314
import { ROUTES } from './routes';
14-
import { Questions } from '@/routes/questions/main';
1515

1616
export const router = createBrowserRouter([
1717
{
@@ -27,6 +27,7 @@ export const router = createBrowserRouter([
2727
children: [
2828
{
2929
path: ROUTES.QUESTIONS,
30+
loader: questionsLoader(queryClient),
3031
element: <Questions />,
3132
},
3233
{
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './main';
File renamed without changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './main';

frontend/src/routes/questions/main.tsx

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
1-
import { useEffect, useMemo } from 'react';
2-
import { columns } from './table-columns';
3-
import { QuestionTable } from './question-table';
4-
import { useInfiniteQuery } from '@tanstack/react-query';
5-
import { IGetQuestionsResponse } from '@/types/question-types';
6-
import { useCrumbs } from '@/lib/hooks/use-crumbs';
1+
import { queryOptions, useInfiniteQuery, type QueryClient } from '@tanstack/react-query';
2+
import { Suspense, useEffect, useMemo } from 'react';
3+
import { Await, defer, useLoaderData, type LoaderFunctionArgs } from 'react-router-dom';
4+
75
import { WithNavBanner } from '@/components/blocks/authed/with-nav-banner';
6+
import { Loading } from '@/components/blocks/loading';
7+
import { useCrumbs } from '@/lib/hooks/use-crumbs';
88
import { fetchQuestions, ROWS_PER_PAGE } from '@/services/question-service';
9+
import type { IGetQuestionsResponse } from '@/types/question-types';
10+
11+
import { QuestionTable } from './question-table';
12+
import { columns } from './table-columns';
13+
14+
const getListQuestionsQueryConfig = (pageNumber?: number) =>
15+
queryOptions({
16+
queryKey: ['qn', 'list', pageNumber],
17+
queryFn: async ({ signal: _ }) => fetchQuestions(pageNumber),
18+
});
19+
20+
export const loader =
21+
(queryClient: QueryClient) =>
22+
async ({ params: _ }: LoaderFunctionArgs) => {
23+
return defer({
24+
initialPage: queryClient.ensureQueryData(getListQuestionsQueryConfig()),
25+
});
26+
};
27+
28+
type IQuestionListServiceAPIResponse = Awaited<ReturnType<typeof fetchQuestions>>;
29+
type IQuestionLoaderReturn = Awaited<ReturnType<ReturnType<typeof loader>>>['data'];
30+
type IQuestionLoaderData = { initialPage?: IQuestionListServiceAPIResponse };
931

1032
export function Questions() {
1133
const { crumbs } = useCrumbs();
1234

13-
const { data, error, fetchNextPage, hasNextPage, isError, isFetchingNextPage } = useInfiniteQuery<
35+
const initialData = useLoaderData() as IQuestionLoaderReturn as IQuestionLoaderData;
36+
37+
const { data, fetchNextPage, hasNextPage, isError, isFetchingNextPage } = useInfiniteQuery<
1438
IGetQuestionsResponse,
1539
Error
1640
>({
@@ -22,12 +46,12 @@ export function Questions() {
2246
const totalPages = Math.ceil(lastPage.totalQuestions / ROWS_PER_PAGE);
2347
return nextPage < totalPages ? nextPage : undefined;
2448
},
49+
initialData: {
50+
pages: initialData?.initialPage?.questions ? [initialData.initialPage] : [],
51+
pageParams: initialData?.initialPage?.questions ? [0] : [],
52+
},
2553
});
2654

27-
if (isError) {
28-
console.log(error);
29-
}
30-
3155
useEffect(() => {
3256
if (hasNextPage && !isFetchingNextPage) {
3357
fetchNextPage();
@@ -37,14 +61,20 @@ export function Questions() {
3761
const questions = useMemo(() => {
3862
if (data) {
3963
return data.pages.flatMap((page) => page.questions);
64+
} else if (initialData?.initialPage?.questions) {
65+
return initialData.initialPage.questions;
4066
}
4167
return [];
42-
}, [data]);
68+
}, [data, initialData]);
4369

4470
return (
4571
<WithNavBanner crumbs={crumbs}>
4672
<div className='container mx-auto py-3'>
47-
<QuestionTable columns={columns} data={questions} isError={isError} />
73+
<Suspense fallback={<Loading />}>
74+
<Await resolve={initialData.initialPage}>
75+
<QuestionTable columns={columns} data={questions} isError={isError} />
76+
</Await>
77+
</Suspense>
4878
</div>
4979
</WithNavBanner>
5080
);

0 commit comments

Comments
 (0)