import React, { useEffect, useState } from "react"; import "./Skill.css"; import { Fade } from "react-reveal"; function Skill({ name, color }) { const [style, setStyle] = useState({ borderBottom: `4px solid ${color}` }); window.addEventListener("wheel", () => { let scroll = window.scrollY; console.log(scroll); if (scroll >= 1300) { setStyle({ animation: "load 2s ease-out", display: "block", borderBottom: `4px solid ${color}`, }); } }); return ( <> <div className="skill"> <Fade bottom> <div className="Skill__logo"> <img className="logo__img" src="./images/html-5-logo-svgrepo-com.svg" alt="" /> </div> <div className="skills__about"> <div className="skillitem"> <div className="skill__set"> <div className="skill__Name" style={{ color: color }}> {name} </div> </div> <div style={style} className="loading__skill"></div> </div> </div> </Fade> </div> </> ); } export default Skill;Aquí está mi código y no sé, por alguna razón, el evento de la rueda se activa infinitamente y bloquea mi aplicación. Por favor, si alguien puede decirme cuál es el problema.
No sé, por alguna razón, el evento de la rueda se activa infinitamente y bloquea mi aplicación. Por favor, si alguien puede decirme cuál es el problema.
Cuando se llama a setStyle dentro de la devolución de llamada del oyente de eventos de la wheel , se actualiza el componente Skill , que luego invoca window.addEventListener("wheel", () => { de nuevo; agregando otra devolución de llamada a la window y debido a que la wheel fue lo que se llamó inicialmente, es llamado de nuevo, por lo tanto, repetir este ciclo infinitamente.
Esto se puede solucionar fácilmente agregando la lógica que solo debe ser activada por el primer renderizado dentro de un useEffect que tiene el segundo parámetro como [] , así:
useEffect(() => { window.addEventListener("wheel", () => { let scroll = window.scrollY; console.log(scroll); if (scroll >= 1300) { setStyle({ animation: "load 2s ease-out", display: "block", borderBottom: `4px solid ${color}`, }); } }); }, []); Sin embargo, lo anterior es una solución rápida para su solución. Las propiedades basadas en window deben controlarse de manera realista en el componente principal de la aplicación para evitar la contaminación de variables globales y la mantenibilidad de los detectores de eventos que se ejercen en la aplicación de manera cohesiva.
La razón puede ser porque cuando te desplazas, el evento de la rueda se dispara muchas veces. Puede intentar aplicar un script antirrebote.
// ...more code function debounce(func, timeout = 300){ let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, timeout); }; } window.addEventListener("wheel", debounce(() => { let scroll = window.scrollY; console.log(scroll); if (scroll >= 1300) { setStyle({ animation: "load 2s ease-out", display: "block", borderBottom: `4px solid ${color}`, }); } })); // ...more code El ejemplo lo limita a disparar cada 300 milisegundos, o cada 0.3 de segundo.
Recuerde, cada vez que establece un estado o cambia una propiedad, se incurre en un ciclo de renderizado. Y, en su componente, en cada ciclo de renderizado está configurando un oyente en el evento de scroll que nunca desarmó . Además, una de las acciones en su controlador de escucha es establecer el estado, que invocará otro procesamiento, que crea otro escucha, para invocar otro procesamiento; puede ver dónde se acerca esto a una situación similar a un bucle infinito.
Lo que debe hacer es usar el useState , para configurar su controlador solo en el renderizado inicial, y luego devolver una función que desactive el oyente en el desmontaje del componente:
// define handleWheel outside your function, or with `useCallback` to set a persistent reference const handleWheel = () => { let scroll = window.scrollY; console.log(scroll); if (scroll >= 1300) { setStyle({ animation: "load 2s ease-out", display: "block", borderBottom: `4px solid ${color}`, }); } } // later, in your component: useState(() => { window.addEventListener("wheel", handleWheel); return () => window.removeEventListener("wheel", handleWheel); // to be called at unmount of component }, []); // empty array ensures it will be called only at first render