I’m sure during developing complex and big react applications, everybody will struggle with code reusability. One approach is this(custom hook for api calls). Let’s go for creating them.
First of all i’m sorry about my bad writing, my language is not originally English š
Of course we have to get data from the server several times in out application. So, how we can handle these need effectively?
useGet custom hook
The code of that custom hook will be like this:
import axios from "axios";
import { useState } from "react";
import { toast } from "react-toastify";
import apiErrors from "../../features/utils/ApiErrorMessages.json"; export default function useGet() { const [getRes, setGetRes] = useState({}); const [getLoading, setGetLoading] = useState(true); const [getError, setGetError] = useState({}); const getData = (url: string | undefined, config: object) => { if (url) { axios .get(url, config) .then((res) => { setGetRes(res.data); setGetLoading(false); }) .catch((err) => { setGetError(err); setGetLoading(false); toast.error(apiErrors.server_network_error); }); } }; return { getData, getRes, getError, getLoading };
}
Explanation: when i was searching for creating hook like this useGet, i was channeling with a problem. That problem was causing a infinite loop in everytime i use that hook! I fixed that by providing a function to call in the usage side from the useGet return instead of calling on its own hook.
You can see it obviously.(getData function)
What really we are doing in that hook is like this:
1-set the needed states
2-declare getData function(this function send a get request to the given url and save response and errors in our states)
3-return all the states and function we wrote
How about the usage? I have to say it will be something like this:
const {getData , getRes , getErrors , getLoading} = useGet() useEffect(() => { async const fetche = () => { await getData({url : '/api/users' , config : {}}); } },[]) // your rendering logic
I don’t know how i was good in explaining what is happening in my codes, but i hope you understand that.
usePost custom hook
The code:
import axios from "axios";
import { useState } from "react";
import apiErrors from "../../features/utils/ApiErrorMessages.json";
import { toast } from "react-toastify"; type postDataProps = { url: string | undefined; data: object; config: object;
}; export default function usePost() { const [postRes, setPostRes] = useState({}); const [postLoading, setPostLoading] = useState(true); const [postError, setPostError] = useState({}); const postData = ({ url, data, config }: postDataProps) => { if (url) { axios .post(url, data, config) .then((res) => { setPostLoading(false); setPostRes(res.data); }) .catch((err) => { setPostLoading(false); setPostError(err); toast.error(apiErrors.server_network_error); }); } }; return { postData, postRes, postError, postLoading };
}
Be happy! The logic is the same. But it is difference in the data property! We know when we wanna post something to the server we have to send data with it. So we send data here too.
It was so easy to implement them. Now you can reuse your calling api functionality across your application!
Maby i don’t do best practices in these hooks well. I’m studing. But it works now.
Don’t forgot reusability.
Happy coding.