TL/DR: Mi función de alternar simple se activa dos veces cuando se hace clic en el botón.
Estoy usando useEffect en un componente React (w/ Next.js) para poder apuntar a la etiqueta :root <html> para la cual necesito que se alterne la clase. El código es el siguiente:
useEffect(() => { const toggleMode = () => { const root = document.documentElement; root.classList.toggle("dark"); console.log("click"); }; const toggleBtn = document.querySelector("#toggle-btn"); toggleBtn.addEventListener("click", toggleMode);Tengo las importaciones necesarias, el código se coloca dentro de la función del componente principal antes de la devolución y no hay ningún error en la consola.
El único problema es que la función se activa dos veces cada vez que se hace clic en el botón y no puedo encontrar ningún motivo o solución en línea.
Realmente agradecería su ayuda y por favor hágamelo saber si me falta alguna información.
¡Salud!
Resolví un problema similar en esta publicación: ¿Por qué mi código NextJS se ejecuta varias veces y cómo se puede evitar?
Su código solo debe ejecutarse una vez si deshabilita el modo estricto de reacción.
Su problema proviene de registrar el detector de eventos sin reaccionar.
Al registrar al oyente a través de
const toggleBtn = document.querySelector("#toggle-btn"); toggleBtn.addEventListener("click", toggleMode);está configurando un nuevo oyente cada vez que se ejecuta la función, incluso si el DOM no está actualizado. Esto podría dar lugar a que varios oyentes se registren y disparen simultáneamente.
Necesita agregar a su oyente de la manera de reacción.
function Component ( props ){ const [ isFirst, setIsFirst ] = useState( true ); const [ toggle, setToggle ] = useState( false ); useEffect(() => { if( isFirst ) { setIsFirst( false ); return; } document.documentElement.classList.toggle("dark"); }, [ toggle ] ); return <div> <button id="toggle-btn" onClick = { e => setToggle( !toggle ) } /> </div> }