-
-
Notifications
You must be signed in to change notification settings - Fork 797
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add useQuery pagination & add pagination to store example (#278)
(minor)
- Loading branch information
1 parent
9c670ef
commit 040deee
Showing
4 changed files
with
92 additions
and
12 deletions.
There are no files selected for viewing
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
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
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,47 @@ | ||
import {Suspense, useState} from 'react' | ||
import {Link, BlitzPage, useQuery} from 'blitz' | ||
import getProducts from 'app/products/queries/getProducts' | ||
|
||
const ITEMS_PER_PAGE = 3 | ||
|
||
const Products = () => { | ||
const [page, setPage] = useState(0) | ||
const [products] = useQuery( | ||
getProducts, | ||
{ | ||
skip: ITEMS_PER_PAGE * page, | ||
first: ITEMS_PER_PAGE, | ||
}, | ||
{paginated: true}, | ||
) | ||
|
||
return ( | ||
<div> | ||
{products.map((product) => ( | ||
<p key={product.id}> | ||
<Link href="/products/[handle]" as={`/products/${product.handle}`}> | ||
<a>{product.name}</a> | ||
</Link> | ||
</p> | ||
))} | ||
<button disabled={page === 0} onClick={() => setPage(page - 1)}> | ||
Previous | ||
</button> | ||
<button disabled={products.length !== ITEMS_PER_PAGE} onClick={() => setPage(page + 1)}> | ||
Next | ||
</button> | ||
</div> | ||
) | ||
} | ||
|
||
const Page: BlitzPage = function () { | ||
return ( | ||
<div> | ||
<h1>Products - Paginated</h1> | ||
<Suspense fallback={<div>Loading...</div>}> | ||
<Products /> | ||
</Suspense> | ||
</div> | ||
) | ||
} | ||
export default Page |
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 |
---|---|---|
@@ -1,23 +1,56 @@ | ||
import {useQuery as useReactQuery} from 'react-query' | ||
import { | ||
useQuery as useReactQuery, | ||
usePaginatedQuery as usePaginatedReactQuery, | ||
PaginatedQueryResult, | ||
QueryResult, | ||
QueryOptions, | ||
} from 'react-query' | ||
import {PromiseReturnType, InferUnaryParam} from './types' | ||
|
||
type QueryFn = (...args: any) => Promise<any> | ||
|
||
// interface QueryFn { | ||
// (...args: any): Promise<any> | ||
// cacheKey: string | ||
// } | ||
interface Options<T> extends QueryOptions<T> { | ||
paginated?: boolean | ||
} | ||
|
||
/** | ||
* Get useQuery result without "data" | ||
*/ | ||
type RestQueryResult<T extends QueryFn> = Omit<QueryResult<PromiseReturnType<T>>, 'data'> | ||
|
||
/** | ||
* Get usePaginatedQuery result without "resolvedData" | ||
*/ | ||
type RestPaginatedQueryResult<T extends QueryFn> = Omit< | ||
PaginatedQueryResult<PromiseReturnType<T>>, | ||
'resolvedData' | ||
> | ||
|
||
export function useQuery<T extends QueryFn>( | ||
/** | ||
* Get "rest" object return value based on paginated option | ||
*/ | ||
type RestReturnType<T extends QueryFn, O extends Options<T>> = O['paginated'] extends true | ||
? RestPaginatedQueryResult<T> | ||
: RestQueryResult<T> | ||
|
||
export function useQuery<T extends QueryFn, O extends Options<T>>( | ||
queryFn: T, | ||
params?: InferUnaryParam<T>, | ||
options: any = {}, | ||
): [PromiseReturnType<T>, Record<any, any>] { | ||
const {data, ...rest} = useReactQuery([(queryFn as any).cacheKey, params], (_, params) => queryFn(params), { | ||
options?: O, | ||
): [PromiseReturnType<T>, RestReturnType<T, O>] { | ||
const queryKey: [string, any] = [(queryFn as any).cacheKey, params] | ||
const queryFunction = (_: string, params: {}) => queryFn(params) | ||
const queryOptions = { | ||
suspense: true, | ||
retry: process.env.NODE_ENV === 'production' ? 3 : false, | ||
...options, | ||
}) | ||
} | ||
|
||
if (options?.paginated) { | ||
const {resolvedData, ...rest} = usePaginatedReactQuery(queryKey, queryFunction, queryOptions) | ||
return [resolvedData as PromiseReturnType<T>, rest as RestReturnType<T, O>] | ||
} | ||
|
||
return [data as PromiseReturnType<T>, rest] | ||
const {data, ...rest} = useReactQuery(queryKey, queryFunction, queryOptions) | ||
return [data as PromiseReturnType<T>, rest as RestReturnType<T, O>] | ||
} |