最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use setTimeout with a Loader - Stack Overflow

programmeradmin3浏览0评论

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 badges
Add a ment  | 

2 Answers 2

Reset to default 3

You 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)

  };
发布评论

评论列表(0)

  1. 暂无评论