T
TanStack2mo ago
rare-sapphire

Is this cursed? Anyone knows a better way to achieve it?

I am using Zustand and i want to trigger the query anytime the value changes. Using useGlobalStore.getState().selectedProvider to not break the rule of hooks does not work, as it isn't reactive. This can be obviously fixed if i just do a proper custom hook instead of just using the queryOptions, but wanted to know if this is accepted or if there is a good way to do it like this, else i'll just make it a custom hook
export function getUsersQueryOptions(params: QueryUserDto) {
// eslint-disable-next-line react-hooks/rules-of-hooks
const adminSelectedProvider = useGlobalStore(
(state) => state.selectedProvider
);
const providerId = adminSelectedProvider ?? undefined;

return queryOptions({
queryKey: queryKeyFactory.list({
providerId,
...params,
}),
queryFn: () => getUsers({ providerId, ...params }),
});
}
export function getUsersQueryOptions(params: QueryUserDto) {
// eslint-disable-next-line react-hooks/rules-of-hooks
const adminSelectedProvider = useGlobalStore(
(state) => state.selectedProvider
);
const providerId = adminSelectedProvider ?? undefined;

return queryOptions({
queryKey: queryKeyFactory.list({
providerId,
...params,
}),
queryFn: () => getUsers({ providerId, ...params }),
});
}
1 Reply
extended-salmon
extended-salmon2mo ago
The problem you have here is that you are trying to create query options that are defined outside of react, while trying to make it reactive. Your query options should likely not know anything about your store, and should be pure. And then if you want it reactive, you should make a hook on top of that. For example, I would structure this like follows
export function getUserQueryOptions(opts: { params: QueryUserDTO, providerId: number | undefined })) {
return queryOptions(...)
}

export function useProviderBoundUserOptions(params: QueryUserDTO) {
const providerId = useGlobalStore((state) => {
return state.selectedProvider ?? undefined
);

return getUserQueryOptions({ providerId, params });
}
export function getUserQueryOptions(opts: { params: QueryUserDTO, providerId: number | undefined })) {
return queryOptions(...)
}

export function useProviderBoundUserOptions(params: QueryUserDTO) {
const providerId = useGlobalStore((state) => {
return state.selectedProvider ?? undefined
);

return getUserQueryOptions({ providerId, params });
}
Or depending on how flexible you need your query options, you could just make a useBoundProviderUserQuery which calls useQuery directly. --- Either way, the TLDR; is that you should create queryOptions to be non-reactive and expect all the necessary dependencies, and then create the necessary hook abstractions to tie it into your necessary lifecycle.

Did you find this page helpful?