const { useState, useEffect } = React;
const Example = () => {
const [isReady, setIsReady] = useState(true);
// On click, set `isReady` to false
const startProcessing = () => {
setIsReady(false);
};
// When `isReady` becomes false, start "processing".
// (You may want to have an instance variable [via a ref]
// to tell you whether to actually do processing, and if
// so what to process.)
useEffect(() => {
if (!isReady) {
// Start "processing"
const done = Date.now() + 3000;
while (Date.now() < done) {
// Busy wait -- NEVER DO THIS IN REAL-WORLD CODE
}
// Done "processing"
setIsReady(true);
}
}, [isReady]);
return <div>
<input type="button" onClick={startProcessing} value="Start Processing (Takes 3 Seconds)" />
<div>isReady = {String(isReady)}</div>
{isReady ? null : <div className="spinner-loader" />}
</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
/*
Credit: jlong @github
Source: https://github.com/jlong/css-spinners
*/
@-moz-keyframes spinner-loader {
0% {
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes spinner-loader {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spinner-loader {
0% {
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/* :not(:required) hides this rule from IE9 and below */
.spinner-loader:not(:required) {
-moz-animation: spinner-loader 1500ms infinite linear;
-webkit-animation: spinner-loader 1500ms infinite linear;
animation: spinner-loader 1500ms infinite linear;
-moz-border-radius: 0.5em;
-webkit-border-radius: 0.5em;
border-radius: 0.5em;
-moz-box-shadow: rgba(0, 0, 51, 0.3) 1.5em 0 0 0, rgba(0, 0, 51, 0.3) 1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) 0 1.5em 0 0, rgba(0, 0, 51, 0.3) -1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) -1.5em 0 0 0, rgba(0, 0, 51, 0.3) -1.1em -1.1em 0 0, rgba(0, 0, 51, 0.3) 0 -1.5em 0 0, rgba(0, 0, 51, 0.3) 1.1em -1.1em 0 0;
-webkit-box-shadow: rgba(0, 0, 51, 0.3) 1.5em 0 0 0, rgba(0, 0, 51, 0.3) 1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) 0 1.5em 0 0, rgba(0, 0, 51, 0.3) -1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) -1.5em 0 0 0, rgba(0, 0, 51, 0.3) -1.1em -1.1em 0 0, rgba(0, 0, 51, 0.3) 0 -1.5em 0 0, rgba(0, 0, 51, 0.3) 1.1em -1.1em 0 0;
box-shadow: rgba(0, 0, 51, 0.3) 1.5em 0 0 0, rgba(0, 0, 51, 0.3) 1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) 0 1.5em 0 0, rgba(0, 0, 51, 0.3) -1.1em 1.1em 0 0, rgba(0, 0, 51, 0.3) -1.5em 0 0 0, rgba(0, 0, 51, 0.3) -1.1em -1.1em 0 0, rgba(0, 0, 51, 0.3) 0 -1.5em 0 0, rgba(0, 0, 51, 0.3) 1.1em -1.1em 0 0;
display: inline-block;
font-size: 10px;
width: 1em;
height: 1em;
margin: 1.5em;
overflow: hidden;
text-indent: 100%;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>