skip to Main Content

I’m developing an online store using React. I have a functionality where, upon clicking a button, a product is added to favorites. After this action, I want to update the profile request (which returns user and favorites).

My code:

// useProfile.ts

import UserService from "@/services/user.service";
import { useQuery } from "@tanstack/react-query";
import { useUser } from "./useUser";

export const useProfile = () => {
  const { user } = useUser();

  const { data } = useQuery({
    queryKey: ['profile'],
    queryFn: () => {
      return UserService.getProfile(user?.id || "");
    },
    select: ({ data }) => data
  });

  return {profile: data};
};
// LikeButton.tsx

import { useRef } from 'react';
import classes from './LikeButton.module.scss';
// @ts-ignore
import { ReactComponent as IconHeart } from '@/assets/img/svg/icon-heart.svg';
import { useProfile } from '@/hooks/useProfile';
import UserService from '@/services/user.service';
import { useMutation, useQueryClient } from '@tanstack/react-query';

interface ILikeButtonProps {
  productId: number;
}

function LikeButton({ productId }: ILikeButtonProps) {
  const { profile } = useProfile();
  const { invalidateQueries } = useQueryClient();

  const { mutate } = useMutation({
    mutationKey: ['toggle favourite'],
    mutationFn: () => UserService.toggleFavourite(productId),
    onSuccess: () => {
      console.log('onSuccess');
      invalidateQueries({ queryKey: ['profile'] });
    },
  });

  const btnRef = useRef<HTMLButtonElement>(null);

  const buttonClasses = profile?.favourites.some((fp) => fp.id === productId)
    ? `${classes.btn_like} ${classes['btn_like--active']}`
    : classes.btn_like;

  return (
    <button
      ref={btnRef}
      className={buttonClasses}
      onClick={() => mutate()}
      data-product-id={productId}
    >
      <IconHeart />
    </button>
  );
}

export default LikeButton;

However, for some reason, invalidateQueries doesn’t seem to work, or perhaps I’m doing something incorrectly… I couldn’t find an answer online 🙁

I added console.log – it works perfectly. But invalidateQueries isn’t being triggered.

2

Answers


  1. Chosen as BEST ANSWER

    The first issue was also that I wasn't returning anything from onSuccess.

    Classic scenario: while waiting for an answer to my question, I found a solution myself. STRANGELY, the code snippet:

    const {invalidateQueries} = useQueryClient();
    
    const { mutate } = useMutation({
      mutationKey: ['toggle favourite'],
      mutationFn: () => UserService.toggleFavourite(productId),
      onSuccess: () => invalidateQueries({ queryKey: ['profile'] }),
    });
    

    isn't working, but an almost identical one is working perfectly:

    const queryClient = useQueryClient();
    
    const { mutate } = useMutation({
      mutationKey: ['toggle favourite'],
      mutationFn: () => UserService.toggleFavourite(productId),
      onSuccess: () => queryClient.invalidateQueries({ queryKey: ['profile'] }),
    });
    

    Maybe someone in the comments will explain how this works...

    P.S. Tnx to this issue


  2. As I’ve figured out in a reproduction you cannot destructure from useQueryClient hook. This means the functions (like invalidateQueries) need to be bound to the QueryClient when executed.

    This will work:

      // cannot destructure invalidateQueries
      const queryClient = useQueryClient();
    
      const { mutate } = useMutation({
        mutationKey: ['toggle favourite'],
        mutationFn: () => UserService.toggleFavourite(productId),
        onSuccess: () => {
          console.log('onSuccess');
          queryClient.invalidateQueries({ queryKey: ['profile'] });
        },
      });
    

    Destructuring DOES NOT work:

      // this won't work
      const { invalidateQueries } = useQueryClient();
    

    And to confirm, when reading the source code, the query client does indeed use thishttps://github.com/TanStack/query/blob/ca6ad31c19c4d0dcfb8b95c462a575bc79c73bae/packages/query-core/src/queryClient.ts#L54.

    If you destructure the invalidateQueries method and then call it, it’s being called without a context, so it doesn’t know how to use this correctly – https://github.com/TanStack/query/blob/main/packages/query-core/src/queryClient.ts#L250-L269

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search