22
loading...
This website collects cookies to deliver better user experience
import React, { useState, useEffect } from 'react';
export const Progress = () => {
const [loading, hasLoaded] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((json) => {
hasLoaded(true);
});
}, 1550);
return () => clearTimeout(timer);
}, []);
return (
<div className={`progress ${loading ? "progress-success" : "progress-failure"}`}>
{loading ? (
<p className="ending-msg">Loaded!</p>
) : (
<svg role="alert" aria-live="assertive">
<rect x="1" y="1" className="border" rx="15" ry="15" />
<rect x="1" y="1" className="filling" rx="15" ry="15" />
</svg>
)}
</div>
);
};
loading
to check whether we are waiting for data or the waiting has ended. This only need be a boolean, because either the progress bar is loading or not. It initially starts off as false, because we haven't requested any data yet.useEffect
is where we can check the loading state and show our progress bar animation if the loading state is true. The sample fetch request is just there to illustrate this point, as you will likely be waiting on some event when using a progress bar. The setTimeout
is just to mock the waiting time, in reality you would not need this since the program would naturally be waiting on whatever it is you need the bar for.fillBar
animation is running for, which we will see in the styles. Basically, it needs to be at least 50 milliseconds longer than the fillBar
animation. You can update this or remove the setTimeout
entirely.height
and width
. Everything else will be handled in the styles..progress-success {
.ending-msg {
color: green;
}
}
.progress-failure {
.ending-msg {
color: red;
}
}
.progress {
.border {
width: 200px;
height: 30px;
stroke-width: 2px;
stroke: blue;
fill: transparent;
}
.filling {
width: 200px;
height: 30px;
fill: blue;
animation: fillBar 1.5s ease-in-out 0s normal 1 forwards;
}
@keyframes fillBar {
0% {
width: 0;
}
30% {
width: 80px;
}
70% {
width: 120px;
}
100% {
width: 200px;
}
}
}
fillBar
keyframe we have running on the svg with the className of .filling
. In fillBar
, we define the progression of how we want to fill the progress bar by simply increasing the width of the svg, which by being inside of the svg with a class name of .border
gives the illusion that it's filling the bar. The actual speed and transition is defined by the way we call the keyframe, seen in the animation
property.