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
+
7
5
import { WithNavBanner } from '@/components/blocks/authed/with-nav-banner' ;
6
+ import { Loading } from '@/components/blocks/loading' ;
7
+ import { useCrumbs } from '@/lib/hooks/use-crumbs' ;
8
8
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 } ;
9
31
10
32
export function Questions ( ) {
11
33
const { crumbs } = useCrumbs ( ) ;
12
34
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 <
14
38
IGetQuestionsResponse ,
15
39
Error
16
40
> ( {
@@ -22,12 +46,12 @@ export function Questions() {
22
46
const totalPages = Math . ceil ( lastPage . totalQuestions / ROWS_PER_PAGE ) ;
23
47
return nextPage < totalPages ? nextPage : undefined ;
24
48
} ,
49
+ initialData : {
50
+ pages : initialData ?. initialPage ?. questions ? [ initialData . initialPage ] : [ ] ,
51
+ pageParams : initialData ?. initialPage ?. questions ? [ 0 ] : [ ] ,
52
+ } ,
25
53
} ) ;
26
54
27
- if ( isError ) {
28
- console . log ( error ) ;
29
- }
30
-
31
55
useEffect ( ( ) => {
32
56
if ( hasNextPage && ! isFetchingNextPage ) {
33
57
fetchNextPage ( ) ;
@@ -37,14 +61,20 @@ export function Questions() {
37
61
const questions = useMemo ( ( ) => {
38
62
if ( data ) {
39
63
return data . pages . flatMap ( ( page ) => page . questions ) ;
64
+ } else if ( initialData ?. initialPage ?. questions ) {
65
+ return initialData . initialPage . questions ;
40
66
}
41
67
return [ ] ;
42
- } , [ data ] ) ;
68
+ } , [ data , initialData ] ) ;
43
69
44
70
return (
45
71
< WithNavBanner crumbs = { crumbs } >
46
72
< 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 >
48
78
</ div >
49
79
</ WithNavBanner >
50
80
) ;
0 commit comments