I have a simple functional ponent where i click a button and it is shown, i am trying to get my imported spinner to show for 2 seconds when the button is clicked and then show my imported ponent after the two seconds, however i am only able to get the spinner to show 2 seconds after the button is clicked and cannot get it to stop
import React, { useState } from "react";
import Hello from "./Hello";
import Spinner from '../Spinner/Spinner'
import "./styles.css";
export default function App() {
const [show, setShow] = useState(false);
const [loading, setLoading] = useState(false);
const helloHandeler = () => {
setTimeout(() => {
setLoading(!loading)
}, 2000)
setShow(!show);
};
if (loading) return <Spinner />
return (
<div className="App">
<h1>Adding a Spinner</h1>
<div className="bodyContainer">
{!show && <button onClick={helloHandeler}>Click me</button>}
{show && <Hello />}
</div>
</div>
);
}
Working example can be found here:
I have a simple functional ponent where i click a button and it is shown, i am trying to get my imported spinner to show for 2 seconds when the button is clicked and then show my imported ponent after the two seconds, however i am only able to get the spinner to show 2 seconds after the button is clicked and cannot get it to stop
import React, { useState } from "react";
import Hello from "./Hello";
import Spinner from '../Spinner/Spinner'
import "./styles.css";
export default function App() {
const [show, setShow] = useState(false);
const [loading, setLoading] = useState(false);
const helloHandeler = () => {
setTimeout(() => {
setLoading(!loading)
}, 2000)
setShow(!show);
};
if (loading) return <Spinner />
return (
<div className="App">
<h1>Adding a Spinner</h1>
<div className="bodyContainer">
{!show && <button onClick={helloHandeler}>Click me</button>}
{show && <Hello />}
</div>
</div>
);
}
Working example can be found here: https://codesandbox.io/s/gallant-engelbart-y3jus
Share Improve this question asked Mar 28, 2020 at 17:13 ShrewdStyleShrewdStyle 5202 gold badges5 silver badges15 bronze badges2 Answers
Reset to default 3You can add useEffect
hook to update the DOM.
You are only updating the loading
flag inside handler. React does not know that it needs to update the DOM.
useEffect(() => {
if (loading) {
setTimeout(() => {
setLoading(false);
}, 2000);
}
}, [loading]);
Forked codesandbox: https://codesandbox.io/s/inspiring-liskov-t53fv
When you trigger helloHandeler()
it is registering the setTimeout()
to start only after two seconds! This is the behaviour of setTimeout()
.
Instead, you should setLoading()
imediatly, and then setTimeout
to stop loading 2sec after. Maybe you would want to setShow()
after the two sec also, so place it inside the setTimeout()
.
update
Also, remmember that JS works asynchronusly, so, when you register setTimeout, the loading
is not true
yet.
const helloHandeler = () => {
setLoading(true)
setTimeout(() => {
setLoading(false)
setShow(!show);
}, 2000)
};