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+
75import { WithNavBanner } from '@/components/blocks/authed/with-nav-banner' ;
6+ import { Loading } from '@/components/blocks/loading' ;
7+ import { useCrumbs } from '@/lib/hooks/use-crumbs' ;
88import { 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
1032export 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