Fetching data using Axios and useEffect results in null before the actual object is loaded.
Unfortunately, I am not able to use object destructuring before the actual object is not empty.
I am forced to use a hook to check whether an object is empty or not.
For instance, I would like to create multiple functions and split my code up in separate functions for better readability.
This is my HTTP request Hook:
import { useState, useEffect } from 'react';
import axios from 'axios';
export const useHttp = (url, dependencies) => {
const [isLoading, setIsLoading] = useState(false);
const [fetchedData, setFetchedData] = useState(null);
useEffect(() => {
setIsLoading(true);
axios
.get(url)
.then(response => {
setIsLoading(false);
setFetchedData(response.data);
})
.catch(error => {
console.error('Oops!', error);
setIsLoading(false);
});
}, dependencies);
return [isLoading, fetchedData];
};
Followed by my page component:
import React from 'react';
import { PAGE_ABOUT, API_URL } from 'constants/import';
import Header from './sections/Header';
import Main from './sections/Main';
import Aside from './sections/Aside';
import { useHttp } from 'hooks/http';
const About = () => {
const [isLoading, about] = useHttp(PAGE_ABOUT, []);
if (!isLoading && about) {
return (
<section className="about">
<div className="row">
<Header
featuredImage={API_URL + about.page_featured_image.path}
authorImage={API_URL + about.page_author_image.path}
authorImageMeta={about.page_author_image.meta.title}
title={about.about_title}
subtitle={about.about_subtitle}
/>
<Main
title={about.page_title}
content={about.page_content}
/>
<Aside
title={about.about_title}
content={about.about_content}
/>
</div>
</section>
);
}
};
export default React.memo(About);
The actual problem I am not able to nest functions before the object is actually returned.
Is there a way to fetch data without a check by any chance? or a cleaner solution would help.
I would like to use multiple components to split up the code.
Any advice or suggestion would be highly appreciated.
To use Axios with the useEffect hook, we just define an async function and call it inside the useEffect callback. Alternatively, we can use the useAxios hook provided by the axios-hooks library.
What you are asking would be bad for UIs. You don't want to block the UI rendering when you're fetching data. So the common practice is showing a Loading spinner or (if you're counting on the request being fast) just rendering nothing until it pops up.
So you would have something like:
const About = () => {
const [isLoading, about] = useHttp(PAGE_ABOUT, []);
if (isLoading) return null; // or <Loading />
return (
<section className="about">
<div className="row">
<Header
featuredImage={API_URL + about.page_featured_image.path}
authorImage={API_URL + about.page_author_image.path}
authorImageMeta={about.page_author_image.meta.title}
title={about.about_title}
subtitle={about.about_subtitle}
/>
<Main
title={about.page_title}
content={about.page_content}
/>
<Aside
title={about.about_title}
content={about.about_content}
/>
</div>
</section>
);
};
If your api has no protection for errors and you're afraid of about being null or undefined you can wrap the component with an Error Boundary Component and show a default error. But that depends if you use those in your app.
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With