We have learned how to use useQuery and structure your application when using react query to communicate with your server. This time around we are going to learn how to send data to your server with a seamless user experience. Let’s get straight into this bad boy. 😏
Why useMutation?
Very different from queries, mutation can be used to post, delete or update your data with react query, even any side effects from your server. And useMutation is the hook used to perform this.
useMutation In Action ⚔️
Following our layer pattern from the scaffolding guide we are going to write our add planet API in our api.js layer as
const addPlanet = async (data) => {
const { name } = data;
const body = { name };
return axiosInstance({
url: "planets",
method: "POST",
data: body,
}).then(({ data }) => {
return data;
});
};
Once we have the api layer ready we then consume it in our custom hooks hooks.js as
const useAddPlanet = () => {
const queryClient = useQueryClient();
queryClient.setMutationDefaults(["add-planet"], {
mutationFn: (data) => addPlanet(data),
onMutate: async (variables) => {
const { successCb, errorCb } = variables;
return { successCb, errorCb };
},
onSuccess: (result, variables, context) => {
if (context.successCb) {
context.successCb(result);
}
},
onError: (error, variables, context) => {
if (context.errorCb) {
context.errorCb(error);
}
},
});
return useMutation(["add-planet"]);
};
we are setting our mutation defaults as the first argument being the query key and then our mutation function like we did in react query. The new kids in the town here are onMutate, onSuccess and onError.
- onMutate: On mutate can be used to handle some side effects when the request is in the process.
- onSuccess: On success is used to do changes when the request is successfully served.
- onError: On error is used to handle if your request is failed or let’s say has some error like 404.
And then we return our mutation with the query key with useMutation. 🚀🚀
Consuming Our Mutation
Now to consume our mutation hook inside our component we can do something like
const addPlanetMutation = useAddPlanet();
and on callback to our add button we do
// ADD PLANET
function handleAddPlanet() {
const planetName = newPlanetInput.current.value;
if (planetName === "") {
return;
}
const mutationArgs = {
name: newPlanetInput.current.value,
successCb,
errorCb,
};
addPlanetMutation.mutate(mutationArgs);
newPlanetInput.current.value = null;
}
We have our mutation arguments ready as mutationsArgs and in them, we have our success and error callbacks which are to be called inside our custom hook.
Success and Error Callbacks
In our error callback, we can add some sort of alert or a way to inform the user that the request they just made has failed and in our success callback we fetch our data.
What Is invalidateQueries?
Invalidate queries come in very handy when we are trying to fetch our data again amid some side effect. And we can pass query key as the argument which tells react query exactly which request or which cached data to fetch again.
const successCb = () => {
queryClient.invalidateQueries(["get-planets"]);
};
const errorCb = () => {};
Invalidate Query Loading
Once we invalidate our query we have to show some sort of indicator to our user that the data is currently being fetched and this too is provided by react query 🤯🤯
const { data, isLoading, isFetching } = usePlanets();
isFetching is used to show the loader again and also addPlanetMuttion.isLoading.
{isLoading || addPlanetMutation.isLoading || isFetching ? (
<InfinitySpin width="500" color="blue" />
) : (
// SHOW COMPONENT
)
BOBS YOUR UNCLE 😁
Wrap Up
OUFFFF 😅😅. This one was very long but I hope you stuck by my side till the very end because if you get this bit it can come in real handy in your reactJS application as well. This is it for this one and I hope to see you at the next one. So this is not a goodbye.
💬 Leave a comment