Reputation: 171389
NextJS app, renders a Header plus one of the Homepage/Contacts/About pages:
Simplified _app.tsx
export default function MyApp({ Component, pageProps }: Props) {
return (
<>
<Header />
<Component {...pageProps} />
</>
);
}
The Contacts page has several filters and it uses a custom useContacts
hook (which uses useQuery
from react-query
) to fetch and render the matched contacts.
Simplified Contacts page
export default function ContactsPage() {
const [filters, setFilters] = useState(...);
const contactsInfo = useContacts(filters);
// render matched contacts
}
The Header has a button which invokes a modal that allows searching people on the platform and adding them as contacts.
When a contact is added successfully, and the user is on the Contacts page, I'd like to refetch the contacts (with all the currently selected filters) so that the newly added contact is immediately visible on the page (assuming they pass the currently selected filters).
It feels that I'd like to call contactsInfo.refetch()
somehow, but I don't have access to contactsInfo
in Header.
Add to contact success callback
onSuccess: () => {
if (isContactsPage()) { // assume we have a way to identify this
// How can I have access to `contactsInfo` here?
contactsInfo.refetch();
}
}
Any tips how to best structure this?
Upvotes: 5
Views: 4780
Reputation: 6633
When a contact is added successfully, and the user is on the Contacts page, I'd like to refetch the contacts (with all the currently selected filters) so that the newly added contact is immediately visible on the page (assuming they pass the currently selected filters).
The correct way to handle this is to invalidate the query. This can be done from anywhere in the application and will only cause a re-fetch if the query being invalidated is active. In this way it's safe to invalidate the query in cases where it would not be efficient to re-fetch.
e.g. in your mutation hook...
const queryClient = useQueryClient();
const onSuccess = () => queryClient.invalidateQueries(contactsQueryKey);
//.. pass the onSuccess to the options of the useMutation hook.
Upvotes: 7
Reputation: 2433
In mycase, i use queryClient.refetchQueries
to conditioned refetch multiple query outside my component.
For example
queryClient.refetchQueries({
predicate: (query) => {
// Every query was called in app life will be trigger once, return true to refetch it query.
// Example: all query was get students will be refetch, whatever class they are
if(query.queryKey.includes('students')){
return true;
}
// Example: only query was get students in classRoomId="001" will be refetch
if(query.queryKey.includes('students') && query.queryKey.includes('001')){
return true;
}
}
})
Easest way for queryKey is bind your query by a unique named and parameter will make every query unique and easy to find.
export const useStudentsQuery = (classRoomId: string) => {
return useQuery(
['students', classRoomId], // <- queryKey
async () => {
const res = await http.getAsync<undefined, Student[]>(`class/${classRoomId}/students`);
return res.data;
},
{
enabled: !!classRoomId,
}
);
};
Learn more about refetchQueries.
Upvotes: 1