I always have to search for how to do this or refer back to my previous code whenever I work with fetch
. For a while, I've used the solution to this SO question. It's a correct solution and it works great but to be honest, I couldn't really explain very well what was going on if someone asked me to explain that piece of my code. So I thought of a simple way to do it. It's very simple really, I think I was just overthinking it. Here's how:
Setting up the HTML
<!-- this will show our spinner -->
<div id="spinner"></div>
<!-- And this will fetch our data -->
<button onclick="fetchData()">Load data</button>
Creating the CSS spinner
#spinner{
visibility: hidden;
width: 80px;
height: 80px;
border: 2px solid #f3f3f3;
border-top:3px solid #f25a41;
border-radius: 100%;
position: absolute;
top:0;
bottom:0;
left:0;
right: 0;
margin: auto;
animation: spin 1s infinite linear;
}
@keyframes spin {
from {
transform: rotate(0deg);
} to {
transform: rotate(360deg);
}
}
#spinner.show {
visibility: visible;
}
The spinner visibility is hidden by default. This is the element we'll manipulate in order to show and hide it as desired.
Getting things working with Javascript
I'll use the random user generator api.
const spinner = document.getElementById("spinner");
function showSpinner() {
spinner.className = "show";
setTimeout(() => {
spinner.className = spinner.className.replace("show", "");
}, 5000);
}
// function hideSpinner() {
// spinner.className = spinner.className.replace("show", "");
// }
function loadData() {
showSpinner()
fetch('https://randomuser.me/api/')
.then(response => response.json())
.then(data => {
// hideSpinner()
console.log(data)
});
}
When showSpinner()
is called, it adds a show
class to the spinner
element, which turns the visibility: visible
as we specified in the css. To hide the spinner, the show
class is removed which turns the visibility: hidden
.
For demonstration purposes, I've used a timeout function and set it to 5 seconds so the spinner can load since fetching the data takes like 1 second. But ideally, you'd want to have a hideSpinner()
function and call that after the data has been returned. Then, the timeout time should be increased to maybe 15 seconds since you don't want it to load forever, after which you'd show an error.
Here's the pen
Top comments (12)
This is largely irrelevant to your post :), but you can replace
with
which I think makes things a little easier to read and won't interfere with any existing classes.
Very nice. Didn't know about that 😀
Getting JavaScript to interact with CSS is a really good way to handle this.
Just for personal preference, I'd probably use the built-in hidden attribute, rather than having a
show
class. I'd also animate as small an area as possible by moving the spinner to a pseudo-class.Great work 🙂
Oh this is good! spinner is gone as the promise is resolved!
Nice I love to have script on my newly develop blog site.
You did a common mistake, to not hide the spinner at error, see promise.catch().
I know that error handling is a tabu subject in the JS ecosystem, but we should change this.
Didn’t know about promise.catch. I’ll check it out. Thanks!
Thanks a lot ! Very clear explanation
But then, there's a catch. How is it related to the time of loading data. As in, it will always load for 5 seconds irrespective of the actual loading time, isn't it?
ya.he just put it there for demonstration.
Thank you very much bro. It's easier than I thought.
Great .Is there a way to change the loading icon animating speed based upon the content fetched uptill now . Should spin fast if content is about to fully download