Hello folks,
Frontend apps are not complete if there are no api calls involved and calling an api becomes a little repetitive thing to do. By cre...
Some comments have been hidden by the post's author - find out more
For further actions, you may consider blocking this person and/or reporting abuse
Hello,
here is a reviewed code for final solution :
and to use it :
This is a really good optimisation, specially the
axios.request
👏Two points to consider here -
JSON.stringify
andJSON.parse
was used to avoid possibility of any errors.Thanks for sharing this 🙌
Exactly what I was thinking while reading the post XD. And maybe wrap this in React Query for an even juicier hook!
You can get it here :
httpss://github.com/ecyrbe/react-axios-query
It's juste a wrapper. Really simple.
Correct link :)
github.com/ecyrbe/react-axios-query
There is small syntax error in losing callback. instead of setloading it should be setLoading. `import { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'jsonplaceholder.typicode.com';
/**
fixed :
`import { useState, useEffect } from 'react';
import axios from 'axios';
axios.defaults.baseURL = 'jsonplaceholder.typicode.com';
/**
fixed :
axios already support generic request in one parameter, no need to call specialized ones
**/
export const useAxios = (axiosParams) => {
const [response, setResponse] = useState(undefined);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const fetchData = async (params) => {
try {
const result = await axios.request(params);
setResponse(result.data);
} catch( error ) {
setError(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData(axiosParams);
}, []); // execute once only
return { response, error, loading };
};`
Hi, small fix:
here
const [loading, setloading] = useState(true);
to
const [loading, setLoading] = useState(true);
upperCase "L"
Greetings
A correction:
Add axiosParams to the empty list in the second param of the useEffect hook. This will remove a dependency error
Wow
sir what if the structure has axios interceptor and header is with bearer token?
Nice article and well explained! If you want to go further with the hook I always recommend this article of Kent C Dodds about not using booleans for loading
Yes, that is also a good approach. But, if I am using reducers, I just go with states as reducers help us updating states synchronously.
Reducers can also be useful when the different states are closely related, although both options are good in this case :)
I believe your
fetchData
function is getting recreated on every render of the hook. Consider moving it into auseCallback
. I'm curious what other people think about that or if I'm missing something. Nice hook!useCallback don't magically make the function not being recreated... it just makes sure the instance created the first time is used the second time, etc... but unfortunately function creation is still done at runtime, so no performance gain from using useCallback.
So you should only use useCallback if you need a stable function instance for referencing in another component.
Since fetchData is only used internally and not exposed outside the hook, useCallback will in fact bring a memory cost and no performance gain.
See this article or this one for another explanation
Yeah, I knew the primary purpose of useCallback was for a stable reference but I also thought it was important in some cases for performance reasons. Those articles are helpful for understanding that that's not a big deal. Thanks!
Really good explanation here! Even I wondered initially if useCallback will make any difference. Thanks for sharing!
Any issue occurred? Can you please share details?
Nice hook!
I will try that in my projects. Thank you for sharing!
I just would return the hooks states as an array, so I can rename it.
return [ response, error, loading ];
const [ products, productsError, productsLoading ] = useAxios(params);
In case a I need more than one api request in the same component, I can differentiate them.
You can rename with object returns as well
Hey, that's a nice improvement!
Other potential enhancements:
Add local storage and stale state cache, to show stale whilst loading new version.
Add withAxios HOC to wrap and inject these properties into any "dumb" component.
Provide an example extending the hook to tailored hooks:
const usePost = id => useAxios('/api/posts/' + id);
... It's an option for grouping your data access into a secondary layer, so components then just hooks the most basic hooks.
Providing examples to disable/mock the fetch in unit tests is a handy one to consider ... Storybook too ... Like having a testData parameter which is used if typeof window != 'object', or jest mocking.
Finally a withAxiosDisplay HOC could wrap that with a loader overlay, loading spinner or skeleton display, error display, and then child component, so you get this:
let Post = ({data}) => {
// Just render from data
};
const Post123 = withAxiosDisplay('/api/post/123', Post):
// Render
... Loading display, error handler, retry and passing data then all included.
wow, great job that looks nice, but it might be impractical to use for POST methods as you want to control the triggering of the request, like when user submit a form, but hooks are triggered once the component is loaded and you can't use it inside a function or a condition,
what about implementing same as Apollo does, if the method is POST, you dont trigger the fetchData yourself, but return it with the other variables.
I also agree with the comment below that suggest using an array so we can rename it on use, so it can be used multiple times same component, like GET the saved form values, then POST after the user fill the rest of the form and submit
I was thinking the same, but then even if we return the fetch method, we just cannot use a custom hook inside an event handler. Then we have to revert back to a normal js function or a fetch component, no more a custom hook. React is weird. I didn't find any standard way to achieve this
I've used this solution with TypeScript and added an option to cancel the request:
nice post I recommend a change from then/catch to async/await approach
Hello,
This is good. However, I want to ask if I want to use in onClick function. Something like calling the hook on user login. How can we do it ?
I also want this.
Never understood quite the use of hooks like this. Requests should not be made from inside components, mainly due to separation of concerns and specially in the case that you might need to make the same request from multiple places in you application. So would you use that twice in 2 diferent components?
The only point I see in using this is for a quick prototype to trash the next day.
Personally since I also use redux-sagas, there is usage for me.
But still a good tutorial :)
Nice! But it's more useful to export a fetch action instead of the data. This way you can fetch data when you need it instead of doing it only on mount. You also need something like redux or context to set/get the api response.
Nice hook!
In component:
Unfortunately, I have to admit that this custom hook is futile and impractical. Could you please give a real-life example instead of making a request manually like
useAxios({ data: "HAHA look" })
?Like @anastawfik mentioned, it's not possible to call this hook inside a JavaScript function, i.e. the submit handler, which is like 90% of cases where we would need such a hook in the first place.
In any case, it's more to do with React.
A little modification and you can use it on click.
Read here
try use swr
Great example, but i have a some question.
How can invoke this custom Hook from a button? (Post Request)
you need to learn about react query or useSWR.
noted 😇
I made a get call to fetch the posts using get method, but I want to make a post reuest when user clicks on Add button , so I am calling the hook as ->
this is causing error , how can I make a post request then.
codesandbox.io/s/currying-bush-yic...
Interesting, though a few things I'm not clear on.
Worth Reading! ❤️
you need to learn about react query or useSWR
what if I want to submit something... kindda confusing!
it will better if you handle load more in your custom hook
I have a error in useEffect. How to fixed?
You can disable it with a comment
// eslint-disable-next-line react-hooks/exhaustive-deps
. Because fetchData need to be called only on mount component cycle.If you want to make it even more advanced, simply load up axios-retry and configure exponential falloff retries in the hook too:
github.com/softonic/axios-retry
Very nice article, simple and direct to the point.
Congrats and keep writing!
Nice!
Thanks, nice code !!!
Simple and clear explanations! Thank you for your efforts.
Keep writing!
@ms_yogii how would you write unit tests for this custom hook?
Thank you it helped me a lot
Cool stuff 👍
Your articles are very lively and interesting
Thank you so much!
very usefull thanks
Finally i found what i needed thank you for the nice blog
I tried to use this code snippets and got cors error.
How to fix it?
nice, good useful
It's great, but do you have any idea to add request cancellation feature to this hook?