Allow computed props in keys #Vue
AlmarAubel opened this issue · 6 comments
As a Vue user it would be really nice if I could use Computed props a key names
See this example from tanstack query website ->
// Get the user
const { data: user } = useQuery({
queryKey: ['user', email],
queryFn: () => getUserByEmail(email.value),
})
const userId = computed(() => user.value?.id)
const enabled = computed(() => !!user.value?.id)
// Then get the user's projects
const { isIdle, data: projects } = useQuery({
queryKey: ['projects', userId],
queryFn: () => getProjectsByUser(userId.value),
enabled, // The query will not execute until `enabled == true`
})
For example
export const todoQueries = createQueryKeys('todos', {
getTodo: (todoId: Ref<string | undefined>) => ({
queryKey: [todoId],
queryFn: () => aanvraagApi.aanvraagGetHvv(todoId.value!)
})
});
Give the following error on getTodo
TS2322: Type '(todoId: Ref<string | undefined>) => { queryKey: [Ref<string | undefined>]; queryFn: () => Promise<AxiosResponse<Result1OfManagementAPIAanvragenPublicHvvDto>>; }' is not assignable to type 'FactoryProperty | DynamicKey'.
Type '(todoId: Ref<string | undefined>) => { queryKey: [Ref<string | undefined>]; queryFn: () => Promise<AxiosResponse<Result1OfManagementAPIAanvragenPublicHvvDto>>; }' is not assignable to type 'DynamicKey'.
Type '{ queryKey: [Ref<string | undefined>]; queryFn: () => Promise<AxiosResponse<Result1OfManagementAPIAanvragenPublicHvvDto>>; }' is not assignable to type 'KeyTuple | QueryKeyRecord | DynamicQueryFactoryWithContextualQueriesSchema | DynamicQueryFactorySchema | DynamicKeySchemaWithContextualQueries'.
Type '{ queryKey: [Ref<string | undefined>]; queryFn: () => Promise<AxiosResponse<Result1OfManagementAPIAanvragenPublicHvvDto>>; }' is not assignable to type 'DynamicQueryFactorySchema'.
Type '{ queryKey: [Ref<string | undefined>]; queryFn: () => Promise<AxiosResponse<Result1OfManagementAPIAanvragenPublicHvvDto>>; }' is not assignable to type 'QueryKeyRecord'.
Types of property 'queryKey' are incompatible.
Type '[Ref<string | undefined>]' is not assignable to type 'readonly [ValidValue]'.
Type 'Ref<string | undefined>' is not assignable to type 'ValidValue'.
Type 'Ref<string | undefined>' is not assignable to type 'AnyObject'.
Index signature for type 'string' is missing in type 'Ref<string | undefined>'.
Currently I get an type error when I translate this example to the query key factory.
https://tanstack.com/query/v4/docs/vue/guides/dependent-queries
@AlmarAubel thanks for raising this issue! I'm not familiar with the Vue API so I'm trying to understand its particularities on the example you've shared. What are the trade offs when defining queryKey: ['projects', userId]
vs queryKey: ['projects', userId.value]
Yes I understand it's very specific for Vue. Vue uses a concept called reactivity where a variable can be wrapped by a reactive object var x= ref(1)
when x is update x.value = 2
it will automatically rerender the virtual dom( or trigger other functions).
When I do userId.value it will unwrap the value an dloose the reactivity so when userId is updated it will not update the key. In vue-query it works fine. I understand that this library is framework agnostic. If I have some time left next week I will look how vue-query handles reactive var and look how it could be used to extend this framework.
In the example above the computed function return some kind of reactive var (but is read-only)
@AlmarAubel I'm preparing a new release that will support your use-case
@AlmarAubel version v1.1.0
has been released and should fix your issue!
Whoo thank you very much. Will try it out tomorrow!
Tested it this morning and the following example is working! Great work
Full working example here -> https://github.com/AlmarAubel/vue-query-computed-support
const userId = ref<string>("")
const userQueries = createQueryKeys('users', {
detail: (userId: MaybeRef<string>) => ({
queryKey: [userId],
queryFn: () => getUser(unref(userId)),
}),
});
var { data, isLoading, status } = useQuery({
...userQueries.detail(userId),
enabled: computed((() => !!userId.value))
});