Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

134
Views
React - onClick setTimeout/clear old timeout if there is one

I'm doing a toy project where I generate a lot of tints and shades of colors and clicking on them copies their hex values to the clipboard. Originally, I was using an onClick handler on the color article to set my state value alert to true (which would display "copied to clipboard") and using useEffect to set a 3 second timer with setTimeout before turning alert false so that the text would disappear after awhile.

The relevant code inside my Color component:

  useEffect(() => {
    const timeout = setTimeout(() => {
      setAlert(false);
    }, 3000);
    return () => clearTimeout(timeout);
  }, [alert]);

and

  return (
    <article
      className={`color ${index > (list.length - 1) / 2 ? "color-light" : ""}`}
      style={{ backgroundColor: `rgb(${rgbString})` }}
      onClick={() => {
        setAlert(true);
        navigator.clipboard.writeText(hexValue);
      }}
    >
      <p className="percent-value">{weight}%</p>
      <p className="color-value">{rgbToHex(...rgb)}</p>
      {alert && <p className="alert">copied to clipboard</p>}
    </article>
  );

This works, but in the case of multiple clicks on the same color article, I want to have the "copied to clipboard" alert disappear 3 seconds after the last click. In other words, I want multiple clicks to refresh the timer. Currently, it disappears 3 seconds after the first click, so subsequent clicks do not refresh the timer. This is because subsequent clicks on the color don't change the alert state value, so I can't refresh my timer in useEffect. I tried to solve this by calling setAlert(false) before setAlert(true) in my onClick to force the state to change every click and let me enter useEffect by force but this doesn't work. I've also tried different ways of removing useEffect entirely and trying to do everything in the onClick block since it's semantically closer to what I'm trying to do, but I can't figure out how to achieve my result that way. Any pointers?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

What you can do is declare a variable alertTimeout outside of your component:

let alertTimeout;
function MyComponent(props) {
...
}

And in your component you define a function for the timeout triggering/refreshing :

function triggerAlert() {
  if (alertTimeout) {
    clearTimeout(alertTimeout);
  }
  setAlert(true);
  alertTimeout = setTimeout(() => {
    setAlert(false);
  }, 3000);
}

And you call this function with onClick:

onClick={() => {
    triggerAlert();
    navigator.clipboard.writeText(hexValue);
  }}

And you need to add a uesEffect to clear the timeout on component unmount:

useEffect(() => {
  return function cleaning() {
    if (alertTimeout) {
      clearTimeout(alertTimeout);
    }
  }
}, [])
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!