-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
153 additions
and
0 deletions.
There are no files selected for viewing
32 changes: 32 additions & 0 deletions
32
src/app/(AppBarHeader)/toks-main/_components/QuizListServerComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { | ||
HydrationBoundary, | ||
QueryClient, | ||
dehydrate, | ||
} from '@tanstack/react-query'; | ||
import React from 'react'; | ||
|
||
import { CardList } from './CardList'; | ||
import { getQuizList } from '../_lib/remotes/quiz'; | ||
|
||
const QuizListServerComponent = async () => { | ||
const queryClient = new QueryClient(); | ||
await queryClient.prefetchInfiniteQuery({ | ||
queryKey: ['posts', 'recommends'], | ||
queryFn: ({ pageParams }) => | ||
getQuizList({ | ||
page: pageParams, | ||
size: 10, | ||
categoryIds: [1, 2, 3, 4, 5, 6, 7, 8, 9], | ||
}), | ||
initialPageParam: 0, | ||
}); | ||
const dehydratedState = dehydrate(queryClient); | ||
|
||
return ( | ||
<HydrationBoundary state={dehydratedState}> | ||
<CardList /> | ||
</HydrationBoundary> | ||
); | ||
}; | ||
|
||
export default QuizListServerComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
type Props = { page: number; size: number; categoryIds: string[] }; | ||
|
||
export const getQuizList = async ({ page, size, categoryIds }: Props) => { | ||
const queryParams: Record<string, string> = {}; | ||
|
||
if (categoryIds.length > 0) { | ||
queryParams['categoryIds'] = categoryIds.join(','); | ||
} | ||
|
||
queryParams['page'] = String(page); | ||
queryParams['size'] = String(size); | ||
|
||
const searchParams = new URLSearchParams(queryParams).toString(); | ||
const res = await fetch(`api/v1/quizzes?${searchParams}`, { | ||
next: { | ||
tags: ['quiz-list'], | ||
}, | ||
}); | ||
|
||
return res.json(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
export const isEqual = (value: unknown, other: unknown): boolean => { | ||
if (value === other) { | ||
return true; | ||
} | ||
|
||
if (typeof value !== typeof other) { | ||
return false; | ||
} | ||
|
||
if (Array.isArray(value) && Array.isArray(other)) { | ||
if (value.length !== other.length) { | ||
return false; | ||
} | ||
for (let i = 0; i < value.length; i++) { | ||
if (!isEqual(value[i], other[i])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
if ( | ||
typeof value === 'object' && | ||
typeof other === 'object' && | ||
value !== null && | ||
other !== null | ||
) { | ||
const valueObj = value as Record<string, unknown>; | ||
const otherObj = other as Record<string, unknown>; | ||
const valueKeys = Object.keys(valueObj); | ||
const otherKeys = Object.keys(otherObj); | ||
|
||
if (valueKeys.length !== otherKeys.length) { | ||
return false; | ||
} | ||
|
||
return valueKeys.every( | ||
(key) => | ||
Object.prototype.hasOwnProperty.call(otherObj, key) && | ||
isEqual(valueObj[key], otherObj[key]) | ||
); | ||
} | ||
|
||
return value === other; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { | ||
HydrationBoundary, | ||
QueryClient, | ||
QueryKey, | ||
QueryState, | ||
dehydrate, | ||
} from '@tanstack/react-query'; | ||
import { cache } from 'react'; | ||
|
||
import { isEqual } from './isEqual'; | ||
|
||
export const getQueryClient = cache(() => new QueryClient()); | ||
|
||
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; | ||
|
||
interface QueryProps<ResponseType = unknown> { | ||
queryKey: QueryKey; | ||
queryFn: () => Promise<ResponseType>; | ||
} | ||
|
||
interface DehydratedQueryExtended<TData = unknown, TError = unknown> { | ||
state: QueryState<TData, TError>; | ||
} | ||
|
||
export async function getDehydratedQuery<Q extends QueryProps>({ | ||
queryKey, | ||
queryFn, | ||
}: Q) { | ||
const queryClient = getQueryClient(); | ||
await queryClient.prefetchQuery({ queryKey, queryFn }); | ||
|
||
const { queries } = dehydrate(queryClient); | ||
const [dehydratedQuery] = queries.filter((query) => | ||
isEqual(query.queryKey, queryKey) | ||
); | ||
|
||
return dehydratedQuery as DehydratedQueryExtended< | ||
UnwrapPromise<ReturnType<Q['queryFn']>> | ||
>; | ||
} | ||
|
||
export async function getDehydratedQueries<Q extends QueryProps[]>(queries: Q) { | ||
const queryClient = getQueryClient(); | ||
await Promise.all( | ||
queries.map(({ queryKey, queryFn }) => | ||
queryClient.prefetchQuery({ queryKey, queryFn }) | ||
) | ||
); | ||
|
||
return dehydrate(queryClient).queries as Array< | ||
DehydratedQueryExtended<UnwrapPromise<ReturnType<Q[number]['queryFn']>>> | ||
>; | ||
} | ||
|
||
export const Hydrate = HydrationBoundary; |