I'm trying to implement a hook (useFetch(route, dependencies=[])) which will be used to fetch data and return a scalar value, loading, which is used to determine if the user is currently fetching new data.
This works as expected on the initial render (as the default state for loading is true).
The problem occurs on every subsequent render. Due to the loading state being currently set to false (after the initial render), the loading state will remain false for an extra render cycle before it is updated to true at the top of the useEffect().
How can I prevent that extra loading=false render cycle, so the component I use this useFetch() in is immediately aware that data is currently being fetched and that I can display the '...loading' text in the render() (without having to render twice to get to this point).
useFetch
function useFetch(route, successHandler, dependencies = []) {
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(route,
{
method: 'POST',
body: JSON.stringify({}),
headers: {"Content-Type": "application/json"}
})
.then(res => res.json())
.then(
() => {
// Set state data from component here
successHandler();
},
() => {/*...*/})
.finally(() => {
setLoading(false);
});
}, dependencies);
return loading;
}
Component
function Component(){
const [toggle, setToggle] = useState(false);
const [options, setOptions] = useState({});
const loading = useFetch('endpoint',
() => setOptions({foo: 'bar'}),
[toggle]);
return <div>
<button onClick={()=>{setToggle(!toggle)}}>Trigger useFetch()</button>
{loading ? '...loading': options.foo}
</div>;
}
Any help or design suggestions would be appreciated,