Reputation: 473
Here is my setup:
const ParentComponent = ({ post_id }) => {
const { data: post } = useGetPost(post_id); // custom hook with useQuery under the hood
return (
<div>
{post.status === 'published' && (
<div className="margin-bottom">
<ChildComponent post_id={post_id} />
</div>
)}
</div>
);
};
const ChildComponent = ({ post_id }) => {
const { data: post } = useGetPost(post_id);
return <div>{post.title}</div>;
};
Whenever i change post status to 'published' – React Query spawns two getPost requests, first of which, for some reason, returns previous post status and second returns the right one. Problem is gone if i move post.status === 'published'
check to ChildComponent
, but it's not an option because of ChildComponent wrapper element ("margin-bottom") inside ParentComponent. Is there something i don't get?
UPDATE:
useGetPost hook:
export const useGetPost = (post_id) => {
return useQuery<IDiscussion, Error>(
['posts', post_id],
async () =>
await axios
.get(`/api/posts/${post_id}`)
.then((response) => response.data),
);
};
And my mutation function:
export const useUpdatePost = (post_id) => {
const queryClient = useQueryClient();
return useMutation(
async (data) => await axios.put(`/api/posts/${post_id}`, data),
{
onMutate: (data) => {
// updating react query cache before actual save
queryClient.setQueryData(['posts', post_id], (oldData) => ({
...oldData,
data,
}));
},
onSuccess: () => {
queryClient.refetchQueries(['posts', post_id]);
},
},
);
};
Upvotes: 1
Views: 3486
Reputation: 629
ChildComponent mounts after you manually set new query data in "onMutate". The query refetches on mount (default behavior), but mutation is not yet finished, so you see the old status. Then, on mutation success query refetches again and you see updated status.
That is why if your ChildComponent gets mounted unconditionally, you see only one request. You can just get rid of onMutate function and refetch the query only once, after mutation success.
Upvotes: 2