Yes, You heard it right! We are only able to use React hooks directly inside a component. If you put hooks inside a conditional statement or a looping statement we will get error (Error: Invalid hook call.)
Problem
Let us try it by using react-query useMutation or useQuery hook inside conditional statement.
We need to use it conditionally when you use same form component for both adding and editing data.
const submit = async data => {
if (action == "Add") {
const mutation = useMutation({
mutationFn: addCompany, //post
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['companies'] })
},
})
mutation.mutate(data);
}
if (action == "Edit") {
const mutation = useMutation({
mutationFn: editCompany, //put,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['companies'] })
},
})
mutation.mutate(data);
}
};
Above code will result in this error
Solution
Create new custom hook inside hooks folder and return useMutation hook with required properties passed from the component where it is called.
import {useMutation} from "@tanstack/react-query"
const useMutateHook = (properties) => {
return useMutation(properties)
}
export default useMutateHook
Create another file and write code for action=="Add"
In the below code we are just returning Object with mutationFn, onError, onSuccess methods.
// This code should execute when user is in add mode
import APIClient from "../../services/api-client";
const apiClient = new APIClient("/companies");
const addCompany = () => {
return {
mutationFn: data => {
return apiClient.post(data);
},
onError: (error, variables, context) => {
//handle error
},
onSuccess: (data, variables, context) => {
//handle success
},
};
};
export default addCompany;
Look at below code incase you want to know what does api-client.js file contain
import axios from "axios";
export const axiosInstance = axios.create({
baseURL: "http://localhost:3500/api",
});
class APIClient {
endpoint
constructor(endpoint) {
this.endpoint = endpoint;
}
getAll = (queryString) => {
return axiosInstance
.get(this.endpoint+queryString)
.then((res) => res.data);
};
get = () => {
return axiosInstance
.get(this.endpoint)
.then((res) => res.data);
};
post = (body) => {
return axiosInstance
.post(this.endpoint,body)
.then((res) => res.data);
};
put = (id,body) => {
return axiosInstance
.put(`${this.endpoint}/${id}`,body)
.then((res) => res.data);
};
delete = (id) => {
return axiosInstance
.delete(`${this.endpoint}/${id}`)
.then((res) => res.data);
};
}
export default APIClient;
Create another file and write code for action=="Edit"
//This code should execute when user is in edit mode
import APIClient from "../../services/api-client";
const apiClient = new APIClient("/companies");
const editCompany = () => {
return {
mutationFn: data => {
return apiClient.put(data._id, data);
},
onError: (error, variables, context) => {
//handle error
},
onSuccess: (data, variables, context) => {
//handle success
},
};
};
export default editCompany;
Finally import custom useMutation hook, addCompany hook, editCompany hook and use it as per your needs.
const mutation = useMutateHook(action == "Add"? addCompany():editCompany());
If you found this helpful, be sure to leave a 💖 on the post. Thank you!
Top comments (4)
I'm not clear about useMutation hook? Why this is used..
useMutation is used to update the data by using PUT or POST or PATCH etc.
Okay Thanks✨
You're welcome ✨