最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React-Query: Invalidate query for specific id - Stack Overflow

programmeradmin1浏览0评论

Summarize Problem:

I'm trying to invalidate my GET query for making a request to fetch a single user. Since there are many users, I have to 2 query keys on my GET request, fetch-user and id:

useQuery<User, AxiosError>(['fetch-user', id], () => fetchUser(id));  

Whenever I PATCH the user I want to invalidate said request, otherwise the previous (cached) values are shown rather than the updated ones.

How do I invalidate a query with a specific key, in my case fetch-user and an additional key of the id?

Show some code:

Hook for GET user with specific id:

const fetchUser = (id: number): Promise<User> => {
  return axios.get(`/users/${id}`).then((resp) => resp.data);
};
export const useUserData = (id: number) => {
  return useQuery<User, AxiosError>(['fetch-user', id], () => fetchUser(id));
};

Hook for PATCH user with specific id:

const patchUser = (id: number, body: PatchUser): Promise<User> => {
  return axios
    .patch(`/users/${id}`, body, { headers: { 'Content-Type': 'application/merge-patch+json' } })
    .then((resp) => resp.data);
};
export const useUpdateUserData = (id: number, onSuccess: (body: User) => void) => {
  return useMutation<User, AxiosError, PatchUser>((variables) => patchUser(id, variables), {
    onSuccess
  });
};

Using react-query in my page:

  const queryClient = useQueryClient();

  const {
    data: user,
    isLoading: isUserGetLoading,
    isSuccess: isUserGetSuccessful
  } = useUserData(Number(id));

  const OnSuccess = (body: User) => {
    queryClient.invalidateQueries(['fetch-user', 'fetch-all-users']);
  };

  const {
    mutate: updateUser,
    isLoading: isUserPatchLoading,
    isError: isUserPatchError,
    error: userPatchError
  } = useUpdateUserData(Number(id), OnSuccess);

What I've tried:

1. Passing an empty invalidateQueries

queryClient.invalidateQueries();

It works! But all queries are invalidated rather than the specific one I want to invalidate. So this is not an option.

2. Passing the id as a parameter

queryClient.invalidateQueries(['fetch-user', id, 'fetch-all-users']);

Doesn't invalidate the query.

3. Passing the id as a parameter and grouping it to fetch-user

queryClient.invalidateQueries([['fetch-user', id], 'fetch-all-users']);

Doesn't invalidate the query.

Workarounds:

I can change the key of the GET query to contain the id, such as:

export const useUserData = (id: number) => {
  return useQuery<User, AxiosError>([`fetch-user-${id}`], () => fetchUser(id));
};

And then I can invalidate it as:

const OnSuccess = (body: User) => {
  queryClient.invalidateQueries([`fetch-user-${id}`, 'fetch-all-users']);
};

However, I'd like to avoid this.

Summarize Problem:

I'm trying to invalidate my GET query for making a request to fetch a single user. Since there are many users, I have to 2 query keys on my GET request, fetch-user and id:

useQuery<User, AxiosError>(['fetch-user', id], () => fetchUser(id));  

Whenever I PATCH the user I want to invalidate said request, otherwise the previous (cached) values are shown rather than the updated ones.

How do I invalidate a query with a specific key, in my case fetch-user and an additional key of the id?

Show some code:

Hook for GET user with specific id:

const fetchUser = (id: number): Promise<User> => {
  return axios.get(`/users/${id}`).then((resp) => resp.data);
};
export const useUserData = (id: number) => {
  return useQuery<User, AxiosError>(['fetch-user', id], () => fetchUser(id));
};

Hook for PATCH user with specific id:

const patchUser = (id: number, body: PatchUser): Promise<User> => {
  return axios
    .patch(`/users/${id}`, body, { headers: { 'Content-Type': 'application/merge-patch+json' } })
    .then((resp) => resp.data);
};
export const useUpdateUserData = (id: number, onSuccess: (body: User) => void) => {
  return useMutation<User, AxiosError, PatchUser>((variables) => patchUser(id, variables), {
    onSuccess
  });
};

Using react-query in my page:

  const queryClient = useQueryClient();

  const {
    data: user,
    isLoading: isUserGetLoading,
    isSuccess: isUserGetSuccessful
  } = useUserData(Number(id));

  const OnSuccess = (body: User) => {
    queryClient.invalidateQueries(['fetch-user', 'fetch-all-users']);
  };

  const {
    mutate: updateUser,
    isLoading: isUserPatchLoading,
    isError: isUserPatchError,
    error: userPatchError
  } = useUpdateUserData(Number(id), OnSuccess);

What I've tried:

1. Passing an empty invalidateQueries

queryClient.invalidateQueries();

It works! But all queries are invalidated rather than the specific one I want to invalidate. So this is not an option.

2. Passing the id as a parameter

queryClient.invalidateQueries(['fetch-user', id, 'fetch-all-users']);

Doesn't invalidate the query.

3. Passing the id as a parameter and grouping it to fetch-user

queryClient.invalidateQueries([['fetch-user', id], 'fetch-all-users']);

Doesn't invalidate the query.

Workarounds:

I can change the key of the GET query to contain the id, such as:

export const useUserData = (id: number) => {
  return useQuery<User, AxiosError>([`fetch-user-${id}`], () => fetchUser(id));
};

And then I can invalidate it as:

const OnSuccess = (body: User) => {
  queryClient.invalidateQueries([`fetch-user-${id}`, 'fetch-all-users']);
};

However, I'd like to avoid this.

Share Improve this question asked Aug 21, 2022 at 11:35 Wizard-of-KozWizard-of-Koz 1,7872 gold badges13 silver badges13 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Call invalidateQueries for each query you'd like to invalidate.

  const OnSuccess = (body: User) => {
    queryClient.invalidateQueries(['fetch-user']);
    queryClient.invalidateQueries(['fetch-all-users']);
  };
发布评论

评论列表(0)

  1. 暂无评论