Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

136
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda