I created a react custom hook to return a function and the returned function takes a config object and makes axios api calls, the custom hook has three states loading, error and data which is also returned from the custom hook. see this codesandbox for code
So the hook is doing what it's supposed to do I can log the data fine, the view is getting updated with the data but my issue is in this example in app.js where I'm handling api call on a button click data is not available inside that click handler function on the first click but if I click the second time I do see the data (see if statement on line 16 of app.js) ideally instead of console logging I would like to perform some action on the data like dispatch an action to update redux state for example... from my understanding useState inside of my custom hook is async and requires a re-render to get the data so if I were to list data as a dependency in my useEffect hook I can see the data whenever I make the call but I'm a bit confused is there a way to make the data available inside my clickHandler function? to be honest I'm not quite sure if my approach is correct in this case I could be thinking wrong about this whole thing! any insight on this would be appreciated.
I've been on numerous SO, blog posts and youtube videos but most of them are using useEffect hook inside the custom hook and returning data from there which I do not want to do since I want to use the custom hook for api calls on demand whenever I call the function in this case when I click a button.
CodePudding user response:
You could use the useEffect function to see when the data is changed
useEffect(() => {
if (data) {
// Update redux state
}
}, [data]);
I know you didn't want to use useEffect inside of useAxios hook but you can just use it outside of it. React onClick is asyncronous so it will check for the if(data) while it is making the api call API_REQUEST() call so you have to have a useEffect to check when the data is actually update on the hook. Also you could maybe try async and await on those functions?
CodePudding user response:
React doesn't guarantee that the state will be immediately updated after setState()
. This is because state updates are non-blocking which means that code execution within the click handler will not wait for the state update to finish. Even if you try using await
with the API_REQUEST()
, it will still not immediately reflect. State updates will be added to the task queue and the code will continue executing past this point, therefore when it reaches the if statement, the data will not be up to date at this point.
In case of a simple setState()
call, you may pass a callback as a second argument and then you will be able to do anything you want to do with the upto date state value:
setState(counter 1, updated => console.log(updated));
But in this case, since you have a custom hook, you have to implement a similar behavior yourself if you need it, by adding some kind of callback to your custom hook, that will be run after the state is actually updated. It could be done using useEffect()
or some other way.