Replies: 3 comments 4 replies
-
can you show some code about how enabled plays together with your cookie? Do your read the cookie from react state, or is it an imperative access ? |
Beta Was this translation helpful? Give feedback.
-
Here is the current implementation (the working solution in term of described problem).
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { removeCookie } from '@/modules/cookies/utils/removeCookie';
import { getUserQueryKey } from '@/modules/user/hooks/useUser';
import type { UserSessionDeleteMutationOptions } from './useUserSessionDelete.utils';
import { getDeleteUserSessionMutation } from './useUserSessionDelete.utils';
/**
* Deletes current user session and returns `redirectTo` value (string or null)
* from the API response. On success, it also cancels all ongoing /user/* request,
* clears user data from the query client, removes `user_logged_in` cookie and
* redirects to the redirectTo path (if received).
*/
export const useUserSessionDelete = (
options?: UserSessionDeleteMutationOptions,
) => {
const queryClient = useQueryClient();
const userQueryKey = getUserQueryKey(); // ['user']
return useMutation(
getDeleteUserSessionMutation({
...options,
onSuccess: ({ data }, ...args) => {
removeCookie('user_logged_in');
// Reset user data query and trigger useUser rerender so
// every query depending on cookie value will be rerendered.
void queryClient.resetQueries({
queryKey: userQueryKey,
exact: true,
});
// Remove all user queries data
queryClient.removeQueries({
queryKey: userQueryKey,
});
options?.onSuccess?.({ data }, ...args);
if (data.redirectTo) {
window.location.assign(data.redirectTo);
}
},
}),
);
};
import { useQuery } from '@tanstack/react-query';
import type { UserQueryOptions } from './useUser.utils';
import { getUserQuery, isLoggedIn } from './useUser.utils';
/**
* Retrieves user data from the API endpoint `/user`,
* using the useQuery hook.
*
* Hook returns additional property `isLoggedIn`, based on the presence of the
* cookie 'user_logged_in'. It should be used in every place, in query client
* context, where we want to check if the user is authenticated.
*/
export const useUser = (options?: UserQueryOptions) => {
const queryResult = useQuery(
getUserQuery({
...options,
enabled: () => isLoggedIn() && !options?.enabled,
}),
);
const { data, meta } = queryResult.data ?? {};
return {
...queryResult,
data: data ?? undefined,
isImpersonated: meta?.impersonated ?? false,
isLoggedIn: isLoggedIn(),
};
}; while the export const isLoggedIn = () => getCookie('user_logged_in') === 'true'; `` Reading cookie is made with old school way of cookie management. It is not reactive in any way. But I'm just realising that it could be and that could work. I will check it asap. |
Beta Was this translation helpful? Give feedback.
-
I tried with reactive cookie hook, as well as simple Can you share your feedback on our approach to this problem? |
Beta Was this translation helpful? Give feedback.
-
Hi,
I face a problem (though not one I'm unable to work around) with the current behavior of
resetQueries
. My case is that I want to easily remove all user queries data and make UI reactive to this fact, on sucessful user log out. All user queries haveenabled
option defined based onuser_logged_in
cookie. If cookie hasfalse
value, then query should not fetch.Once a user is successfully logged out, we set cookie from
true
tofalse
and callresetQueries
to reset queries starting with key['user']
, but unfortunately before subscribers rerender with the newenabled
flag result,resetQueries
tries to instantly refetch it. There is no opportunity before refetch to force theenabled
flag to change its value.To solve this, I figured out that
enabled
option can be a callback that is invoked before everyresetQueries
refetch. That nicely solves the problem. But I find two disadvantages in this approach:Then, I decided to see if we could achieve a decent working solution globally rather than imperatively, so I tried combining both
resetQueries
andremoveQueries
functions. The first one removes and triggers rerender only for the mainuseUser
hook which returnsisLoggedIn
value and has anenabled
flag with callback, and the second removes all user-related data without notifying subscribers, so not rerendering them.I haven't found any simpler or less complex way to handle this use case. I suppose it could have been much simpler by just allowing to disable refetching which does not respect the new query's
enabled
option value if it has been changed just before. So the option to disablerefetch
(boolean) inresetQueries
would be welcome, as it would set the data to initial and notify and rerender hooks/components but without this problematic refetching.Beta Was this translation helpful? Give feedback.
All reactions