El valor de estado showMenu
no se actualiza dentro del gancho useEffect
.
Al realizar la prueba, cuando se hace clic por primera vez en el botón y se toca la pantalla para moverse, showMenu
se consuela correctamente a true
. Cuando se hace clic en el botón por segunda vez (y tercero, adelante, etc.) y se toca la pantalla para moverse, showMenu
continúa consolando como true
cuando debería alternar a false
.
const [showMenu, setShowMenu] = useState(false)
useEffect(_ => {
const listener = e => {
e.preventDefault()
console.log(showMenu, ' useEffect - touchmove')
}
showMenu
? document.body.addEventListener('touchmove', listener, {passive: false})
: document.body.removeEventListener('touchmove', listener)
}, [showMenu])
return (
<button onclick={_ => {
console.log(!showMenu, ' button click')
setShowMenu(!showMenu)
}} />
)
Resultado de la consola
2 respuestas
Creo que el evento del cuerpo no se elimina correctamente, porque el oyente se cambia cada vez useEffect
.
Por lo tanto, puede devolver una función en useEffect
para borrar la useEffect
anterior.
useEffect(() => {
if (showMenu) {
const listener = e => {
e.preventDefault();
console.log(showMenu, ' useEffect - touchmove');
};
document.body.addEventListener('touchmove', listener, { passive: false });
return () => {
document.body.removeEventListener('touchmove', listener);
}
}
}, [showMenu]);
También puede leer cleaning-up-an- efecto para obtener más información
No sé cuál es tu intención, pero lo que estás haciendo con useEffect
probablemente no sea lo que esperas. Cuando showMenu
es false
, está eliminando una función listener
que no se ha vinculado porque los objetos se comparan por referencia en JS y listener
se redefine cada vez {{ X5}} cambios.
La forma típica de desvincular un oyente cuando useEffect
cambia es devolver una función que maneja la limpieza de su devolución de llamada useEffect
. Al igual que:
useEffect(() => {
const listener = e => {
e.preventDefault()
console.log(showMenu, ' useEffect - touchmove')
}
document.body.addEventListener('touchmove', listener, { passive: false })
return () = {
document.body.removeEventListener('touchmove', listener, { passive: false })
}
}, [showMenu])
Preguntas relacionadas
Nuevas preguntas
javascript
Para preguntas sobre la programación en ECMAScript (JavaScript / JS) y sus diversos dialectos / implementaciones (excepto ActionScript). Incluya todas las etiquetas relevantes en su pregunta; por ejemplo, [node.js], [jquery], [json], etc.