1

My UI is not updating on the creation of a project with invalidateQueries. I have confirmed that the database updates are being made successfully and the onSuccess functions are being called. I'm unsure what I am doing wrong, and would love some help.

useProjects.ts

import { getProjects } from 'queries/get-projects';
import { useQuery } from 'react-query';

function useGetProjectsQuery() {
  return useQuery('projects', async () => {
    return getProjects().then((result) => result.data);
  });
}

export default useGetProjectsQuery;

get-project.ts

import { supabase } from '../utils/supabase-client';

export const getProjects = async () => {
  return supabase.from('projects').select(`*`);
};

useCreateProject.ts

import { useUser } from '@/utils/useUser';
import { createProject } from 'queries/create-project';
import { useMutation, useQueryClient } from 'react-query';

export const useCreateProject = () => {
  const { user } = useUser();
  const queryClient = useQueryClient();

  return useMutation(
    ({ title, type, bgColorClass, pinned }: any) => {
      return createProject(title, type, bgColorClass, pinned, user.id).then(
        (result) => result.data
      );
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries('projects');
      }
    }
  );
};

create-project.ts

import { supabase } from '../utils/supabase-client';

export async function createProject(
  title: string,
  type: string,
  bgColorClass: string,
  pinned: boolean,
  userId: string
) {
  return supabase
    .from('projects')
    .insert([
      { title, type, bg_color_class: bgColorClass, pinned, user_id: userId }
    ]);
}

Home Component

const { data: projects, isLoading, isError } = useGetProjectsQuery();
const createProject = useCreateProject();

const createNewProject = async () => {
    await createProject.mutateAsync({
      title: projectName,
      type: selectedType.name,
      bgColorClass: _.sample(projectColors),
      pinned: false
    });
  };

_app.tsx

  export default function MyApp({ Component, pageProps }: AppProps) {
 const [initialContext, setInitialContext] = useState();
 const [supabaseClient] = useState(() =>
   createBrowserSupabaseClient<Database>()
 );
 useEffect(() => {
   document.body.classList?.remove('loading');
 }, []);

 const getUserDetails = async () =>
   supabaseClient.from('users').select('*').single();
 const getSubscription = async () =>
   supabaseClient
     .from('subscriptions')
     .select('*, prices(*, products(*))')
     .in('status', ['trialing', 'active'])
     .single();

 const getInitialData = async () => {
   const userDetails = await getUserDetails();
   const subscription = await getSubscription();
   setInitialContext({
     //@ts-ignore
     userDetails: userDetails.data,
     subscription: subscription.data
   });
 };

 const queryClient = new QueryClient({
   defaultOptions: {
     queries: {
       retry: 0
     }
   }
 });

 useEffect(() => {
   getInitialData();
 }, []);

 return (
   <QueryClientProvider client={queryClient}>
     <SessionContextProvider supabaseClient={supabaseClient}>
       <MyUserContextProvider initial={initialContext}>
         <SidebarProvider>
           <Component {...pageProps} />
           <ReactQueryDevtools initialIsOpen={false} />
         </SidebarProvider>
       </MyUserContextProvider>
     </SessionContextProvider>
   </QueryClientProvider>
 );
}

I have tried moving the onSuccess followup calls to the Home component, and within the hooks, neither one updates the UI. I'm unsure what I am doing wrong and the react query devtools is not helpful.

2
  • Can you show us where you instantiare your new QueryClient()? Commented Jan 14, 2023 at 23:31
  • @adsy Using NextJS, it is initiated in _app.tsx. Updated the main message. Commented Jan 14, 2023 at 23:35

1 Answer 1

3

You are instantiating QueryClient on every render pass so the cache of query keys is being torn down and rebuilt often.

Instantiate this outside of render:

const queryClient = new QueryClient({
   defaultOptions: {
     queries: {
       retry: 0
     }
   }
});

export default function MyApp({ Component, pageProps }: AppProps) {
 const [initialContext, setInitialContext] = useState();
 // ... etc

This will ensure the client is always stable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.