When using React as a frontend that consumes API data, Redux is definitely your friend. You can use hooks to fetch your API data directly into the Redux Store upon page load, making it available for the entire React app to use going forward. There is a small problem with doing this however. If you have a lot of data to load, your page itself will take a long time to load, leaving your users experiencing a site freeze. No good! Luckily there’s a middleware called "Thunk" which can be applied, allowing you to fetch that data asynchronously. This will let your page to continue loading while your data is being gathered from the API, preventing that freeze.
Unfortunately, while technically the page will now fully load, it will load a blank space where that content is supposed to go, which isn’t always a whole lot better from a user experience point of view...so what can be done about that? Not much, other than to let the user know that:
- the site is still working and not frozen
- there is data on the way, they just need to be a little patient
When you visit a professionally built website that loads a lot of data, you’ll undoubtedly run into a loading animation which accomplishes both of these goals (spinning wheel or an old-school loading bar for example).
Great, you can do that, all that’s left now is the question of how to do it in React? This seems simple enough, just use an if statement to render the products if they exist yet, or else load your animation. The tricky part lies in JSX Syntax. Normally you can write an if statement like so
if (items.length > 0) {
// render products;
} else {
// render animation;
};
BUT, rendering a part of the page conditionally means you’ll need to call the if statement INSIDE the render() function, which doesn't work. To get around it, you can define your if statement outside of the render function as part of a separate method. Then you'd call that method within the render function
separateIfFunction = () => {
if (items.length > 0) {
return <div className=”loading-animation”></div>;
} else {
return items.map(item => <Item property={item.property} key={item.id} />);
};
};
render() {
return (
separateIfFunction();
// any other page elements to be loaded BEFORE API data is rendered
);
};
That works, but to keep it more contained, you can also use the tertiary syntax items.length > 0 ? render products : render animation
and surround the whole thing in brackets. Breaking it into multiple lines for the sake of readability, it will look like this
render() {
return (
{items.length > 0
? <div className=”loading-animation”></div>
: return items.map(item => <Item property={item.property} key={item.id} />);
};
// any other page elements to be loaded BEFORE API data is rendered
);
};
And there you have it. Now, when your page first loads, it can begin fetching data from the API and get on with loading the rest of the content, but let the user know that the data is on its way. Once that data becomes available, it will re-render that part of the page to add the data components.
Top comments (0)