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.
CodePudding user response:
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.