Wouldn’t separating query definition and usage be more desirable? #1097
-
Hi, I just started using
I tried it here https://codesandbox.io/s/react-query-conflicting-fetchfn-definitions-for-same-key-6rqpd and to me it looks like it defeats the purpose of having a cache key (and it’s a scenario I found myself in while developing a real world app). What am I missing? Wouldn’t it be preferable to split query definition and usage into 2 separate steps, like:
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Sure, that would be possible in theory, but it just didn't start out that way because of the simplicity of the API. That said, whenever you find yourself using a |
Beta Was this translation helpful? Give feedback.
-
While custom hooks are preferable, this should be possible in V3: client.setQueryDefaults('users', fetchUsers)
function Component {
const { data } = useQuery<string>('users')
} |
Beta Was this translation helpful? Give feedback.
-
I was just thinking about this too. I came up with this: type SimpleQueryOptions<TData> = Omit<QueryOptions<TData>,'queryKey'|'queryFn'|'_defaulted'>
type SimpleObserverOptions<TData> = Omit<QueryObserverOptions<TData>,keyof QueryOptions>
function createQuery<TResData,TReqData=Json>(queryFn: (req:TReqData) => Promise<TResData>, queryOptions?: SimpleQueryOptions<TResData>) {
const key = id();
return (data: TReqData, observerOptions?: SimpleObserverOptions<TResData>) => useQuery([key,data], () => queryFn(data), {
...queryOptions,
...observerOptions,
})
} Usage: const useUserQuery= createQuery(id => fetchUser(id))
function MyComponent(props) {
const query = useUserQuery(props.userId)
} Something like that anyway. I haven't tested it out yet. I don't think it makes the API any harder to use, it just splits the query in two which should force some better design patterns. Now it's obvious what you need to do if you want to use that same query elsewhere -- you just slap an Should also be less surprising. Now it's clear that And then users can extend it fairly easily too: export function createGetQuery<TResData,TReqData=Record<string,string|number>>(route: string, queryOptions?: SimpleQueryOptions<TResData>) {
return createQuery<TResData,TReqData>(data => {
const url = resolveRoute([route,data])
return getJson<TResData>(url).then(res => res.data)
}, queryOptions)
}
const usePhoneQuery = createGetQuery<PhoneNumbersResData,PhoneNumbersReqData>('twilio.getPhoneNumbers') |
Beta Was this translation helpful? Give feedback.
Sure, that would be possible in theory, but it just didn't start out that way because of the simplicity of the API. That said, whenever you find yourself using a
useQuery(key, fn)
more than once, it's suggested to simply create a custom hook for it. This way, there is (just like you described) a single declaration of functionality that can be shared across the whole app. If we made users define queries before usage, it would work, but would essentially be an unnecessary layer at this point with custom hooks.