skip to Main Content

I am trying to make my web app display a message for a set amount of time whenever a button is pushed, and for said timer to reset whenever the button is pushed again before the time has elapsed. I feel dumb for even asking this, but how do I make it so that the button that starts a timer also resets it when the button is clicked again? Below is my code so far:

import { useState, useEffect } from "react";

export default function App() {
  const [revealed, isRevealed] = useState(false);
  const [time, setTime] = useState(0);

  useEffect(() => {
    let timer;
    if (revealed) {
      clearTimeout(timer);
      setTime(2500);
      timer = setTimeout(() => isRevealed(false), time);
    }
  }, [revealed]);

  return (
    <div>
      <button onClick={() => isRevealed(true)}>Start!</button>
      {revealed ? (
        <p>
          This should stay showing up if you keep clicking on the "Start!"
          button.
        </p>
      ) : null}
    </div>
  );
}

Here is the CodeSandbox demo of my code:
https://codesandbox.io/s/frosty-worker-g9l986?file=/src/App.js

2

Answers


  1. Short answer: clearTimeout() https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout

    Long answer:

    Move timer to the global scope so this can be used for clearing the timeout and resuse it.

    Also, the triggering of the timeout should be in the onClick handler instead of useEffect. So the button should’ve been

          <button
            onClick={() => {
              isRevealed(true);
              clearTimeout(timer);
              timer = setTimeout(() => isRevealed(false), time);
            }}
          >
            Start!
          </button>
    

    See you code in action: https://codesandbox.io/s/dazzling-almeida-xpm449?file=/src/App.js

    Login or Signup to reply.
  2. you set revealed "true" when button is clicked and when revealed is true, click on button doesn’t do anything. the solution I can suggest is that set state in a way that every click on button could change it. for example use the time button is clicked. and to clear timeout you should use useEffect return.

    import { useState, useEffect } from "react";

    export default function App() {
    
      const [time, setTime] = useState();
      const [revealed, isRevealed] = useState(false);
      const delayTime = 2500;
    
      useEffect(() => {
        
        let timer;
        if (time) {
          isRevealed(true);
          timer = setTimeout(() => isRevealed(false), delayTime);
        }
        return(
          () => { clearTimeout(timer)}
        )
      }, [time,delayTime]);
    
      return (
        <div>
          <button onClick={() => setTime(Date.now())}>Start!</button>
          {revealed ? (
            <p>
              This should stay showing up if you keep clicking on the "Start!"
              button.
            </p>
          ) : null}
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search