🕊️ A toolkit for ReactQuery that make ReactQuery hooks more reusable and typesafe
npm install @drtz/react-query-kit---
- Make queryKey strongly related with queryFn
- Manage queryKey in a type-safe way
- Generate a custom ReactQuery hook quickly
- Make queryClient's operations clearly associated with custom ReactQuery hooks
- Set defaultOptions for custom ReactQuery hooks easier and clearer
English | 简体中文
- Installation
- Examples
- Usage
- createQuery
- createInfiniteQuery
- createMutation
- Type inference
- Issues
- 🐛 Bugs
- 💡 Feature Requests
- LICENSE
This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's dependencies:
``bash`
$ npm i react-query-kitor
$ yarn add react-query-kit
- Basic
- Optimistic Updates
- Next.js
- Load-More & Infinite Scroll
`tsx
import { QueryClient, dehydrate } from '@tanstack/react-query'
import { createQuery, inferData } from 'react-query-kit'
type Response = { title: string; content: string }
type Variables = { id: number }
const usePost = createQuery
primaryKey: '/posts',
queryFn: ({ queryKey: [primaryKey, variables] }) => {
// primaryKey equals to '/posts'
return fetch(${primaryKey}/${variables.id}).then(res => res.json())
},
// if u only wanna fetch once
enabled: (data) => !data,
suspense: true
})
// or using the alternative syntax to create
// const usePost = createQuery
// '/posts',
// ({ queryKey: [primaryKey, variables] }) => {
// // primaryKey equals to '/posts'
// return fetch(${primaryKey}/${variables.id}).then(res => res.json())
// },
// {
// // if u only wanna fetch once
// enabled: (data) => !data,
// suspense: true
// }
// )
const variables = { id: 1 }
// example
export default function Page() {
// queryKey equals to ['/posts', { id: 1 }]
const { data } = usePost({ variables, suspense: true })
return (
console.log(usePost.getKey()) // ['/posts']
console.log(usePost.getKey(variables)) // ['/posts', { id: 1 }]
// nextjs example
export async function getStaticProps() {
const queryClient = new QueryClient()
await queryClient.prefetchQuery(usePost.getKey(variables), usePost.queryFn)
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
// usage outside of react component
const data = await queryClient.fetchQuery(
usePost.getKey(variables),
usePost.queryFn
)
// useQueries example
const queries = useQueries({
queries: [
{ queryKey: usePost.getKey(variables), queryFn: usePost.queryFn },
{ queryKey: useProjects.getKey(), queryFn: useProjects.queryFn },
],
})
// setQueryData
queryClient.setQueryData
`
Options
- primaryKey: stringprimaryKey
- Required
- will be the first element of the array of queryKeyenabled: boolean | ((data: TData, variables: TVariables) => boolean)
- false
- Optional
- Set this to to disable this query from automatically running.
- If set to a function, the function will be executed with the latest data to compute the boolean
Expose Methods
- getPrimaryKey: () => primaryKeygetKey: (variables: TVariables) => [primaryKey, variables]
- queryFn: QueryFunction
-
Returns
- queryKey: unknown[]setData: (updater: Updater
- The query key of this custom query.
- queryClient.setQueryData
- it's args similar with but without queryKey
`tsx
import { QueryClient, dehydrate } from '@tanstack/react-query'
import { createInfiniteQuery } from 'react-query-kit'
type Data = { projects: { id: string; name: string }[]; nextCursor: number }
type Variables = { active: boolean }
const useProjects = createInfiniteQuery({
primaryKey: 'projects',
queryFn: ({ queryKey: [_primaryKey, variables], pageParam = 1 }) => {
return fetch(/projects?cursor=${pageParam}?active=${variables.active}).then(res => res.json())
},
getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
})
const variables = { active: true }
// example
export default function Page() {
// queryKey equals to ['projects', { active: true }]
const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
useProjects({ variables, suspense: true })
return (
{project.name}
// nextjs example
export async function getStaticProps() {
const queryClient = new QueryClient()
await queryClient.prefetchInfiniteQuery(
useProjects.getKey(variables),
useProjects.queryFn
)
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
// usage outside of react component
const data = await queryClient.fetchInfiniteQuery(
useProjects.getKey(variables),
useProjects.queryFn
)
`
Options
- primaryKey: stringprimaryKey
- Required
- will be the first element of the arrary of queryKeyenabled: boolean | ((data: TData, variables: TVariables) => boolean)
- false
- Optional
- Set this to to disable this query from automatically running.
- If set to a function, the function will be executed with the latest data to compute the boolean
Expose Methods
- getPrimaryKey: () => primaryKeygetKey: (variables: TVariables) => [primaryKey, variables]
- queryFn: QueryFunction
-
Returns
- queryKey: unknown[]setData: (updater: Updater
- The query key of this custom query.
- queryClient.setQueryData
- it's args similar with but without queryKey
`tsx
import { createMutation } from 'react-query-kit'
const useAddTodo = createMutation(
async (variables: { title: string; content: string }) =>
fetch('/post', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(variables),
}).then(res => res.json()),
{
onSuccess(data, variables, context) {
// do somethings
},
}
)
// or using the alternative syntax to create
// const useAddTodo = createMutation
// async (variables) =>
// fetch('/post', {
// method: 'POST',
// headers: {
// Accept: 'application/json',
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify(variables),
// }).then(res => res.json()),
// )
function App() {
const mutation = useAddTodo({
onSettled: (data, error, variables, context) => {
// Error or success... doesn't matter!
}
})
return (
{mutation.isSuccess ?
onClick={() => {
mutation.mutate({ title: 'Do Laundry', content: "content..." })
}}
>
Create Todo
>
)}
// usage outside of react component
useAddTodo.mutationFn({ title: 'Do Laundry', content: "content..." })
`
Returns
- getKey: () => MutationKeymutationFn: MutationFunction
-
You can extract the TypeScript type of any custom hook with inferVariables or inferData
`ts
import { inferVariables, inferData } from 'react-query-kit'
type Variables = inferVariables
type Data = inferData
``
_Looking to contribute? Look for the [Good First Issue][good-first-issue]
label._
Please file an issue for bugs, missing documentation, or unexpected behavior.
[See Bugs][bugs]
Please file an issue to suggest new features. Vote on feature requests by adding
a 👍. This helps maintainers prioritize what to work on.
[See Feature Requests][requests]
MIT
[npm]: https://www.npmjs.com
[node]: https://nodejs.org
[bugs]: https://github.com/liaoliao666/react-query-kit/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug
[requests]: https://github.com/liaoliao666/react-query-kit/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement
[good-first-issue]: https://github.com/liaoliao666/react-query-kit/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22