Skip to content

Commit

Permalink
Add useQuery pagination & add pagination to store example (#278)
Browse files Browse the repository at this point in the history
(minor)
  • Loading branch information
eliashelleborn authored Apr 27, 2020
1 parent 9c670ef commit 040deee
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 12 deletions.
1 change: 0 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ Closes: ??

<!-- Before/after screenshots, etc. -->


<!-- IMPORTANT: Make sure to check the "Allow edits from maintainers" box below this window -->
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
47 changes: 47 additions & 0 deletions examples/store/app/products/pages/products/paginated.tsx
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
55 changes: 44 additions & 11 deletions packages/core/src/useQuery.ts
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>]
}

0 comments on commit 040deee

Please sign in to comment.