Tengo un componente con otro componente en su interior que solo quiero mostrar si el usuario todavía está flotando después de un breve retraso.
Así que escribí un par de controladores para onMouseEnter y onMouseExit para configurar una variable para mostrar que está suspendida. Luego, después de dormir, si todavía está suspendido, quiero establecer una segunda variable para mostrar el elemento.
Sin embargo, hovered se muestra como false sin importar qué. ¿Por qué?
const [hovered, setHovered] = useState(false); const [show, setShow] = useState(false); console.log('hovered', hovered); // This shows the state correctly const handleEnter = () => { setHovered(true); sleep(2000).then(() => { console.log('checking', hovered); // This always shows false if (hovered) { setShow(true); } }); } const handleExit = () => { setHovered(false); setShow(false); }Solución:
Reemplace la suspensión con una devolución de llamada envuelta de use-debounce para evitar que se dispare varias veces y que el retraso siga funcionando.
const ref = useRef(false); const [hovered, setHovered] = useState(false); const [show, setShow] = useState(false); const handleHover = useDebouncedCallback(() => { if (ref.current) setShow(true); else setShow(false); }, 1000); useEffect(() => { ref.current = hovered; }, [hovered]); useEffect(() => { handleHover() }, [hovered]);Te recomendaría usar useRef hook.
const hoveredRef = useRef(false); const [hovered, setHovered] = useState(false); const [show, setShow] = useState(false); useEffect(() => { hoveredRef.current = hovered; }, [hovered]) useEffect(() => { if (!hovered) return; sleep(2000).then(() => { console.log('checking', hoveredRef.current); if (hoveredRef.current) { setShow(true); } }, [hovered]) const handleEnter = () => { setHovered(true); } const handleExit = () => { setHovered(false); setShow(false); }No lo revisé pero debería estar bien, no tengo el resto de tu código, lo siento
Con respecto a su pregunta Por qué:
const handleEnter = () => { setHovered(true); sleep(2000).then(() => { console.log('checking', hovered); // This always shows false if (hovered) { setShow(true); } }); } SetHover que está llamando aquí no cambia la variable inmediatamente, para todo el código después de esta línea en función, seguirá siendo false . Y en el alcance de la función sleep.then todavía usa un valor "falso" antiguo capturado por el cierre.
Y una pequeña advertencia aquí, el código anterior no es ideal, si pasa el mouse dentro y fuera 5 veces dentro de su retraso de 2 segundos, el código dentro de la suspensión se activará 5 veces con éxito. Pero es inofensivo en su caso, en términos de comportamiento.