<div id="root"></div>
body {
text-align: center;
padding: 2rem;
font-size: 20px;
}
h1 {
margin: 0 0 1rem;
}
button {
font-size: 1.2rem;
padding: 0.5rem 1rem;
}
const { useState, useRef, useEffect } = React;
const App = () => {
const [progress, updateProgress] = useState(10);
const change = () =>
updateProgress((value) => {
return value >= 100 ? 0 : value + 10;
});
return (
<>
<h1>React Percent</h1>
<p>
<progress value={progress} max="100">
{progress}%
</progress>
</p>
<p>
<Progress value={progress} />
</p>
<p>
<button onClick={change}>Add 10%</button>
</p>
</>
);
};
const Progress = ({ value = 0, symbol = "%" }) => {
// initialization of ref with value only happens first time
const oldValue = useRef(value);
const interval = useRef(null);
const [display, setDisplay] = useState(oldValue.current);
useEffect(() => {
interval.current && clearInterval(interval.current);
interval.current = setInterval(() => {
setDisplay((val) => {
console.log(val);
if (val >= value) {
oldValue.current = value;
clearInterval(interval.current);
return val;
}
return val + 1;
});
}, 50);
return () => clearInterval(interval.current);
}, [value]);
return (
<span>
{display}
{symbol}
</span>
);
};
ReactDOM.render(<App />, document.querySelector("#root"));
View Compiled
This Pen doesn't use any external CSS resources.