¿Cómo se puede usar el gancho useEffect
(o cualquier otro gancho) para replicar el componentWillUnmount
?
En un componente de clase tradicional, haría algo como esto:
class Effect extends React.PureComponent { componentDidMount() { console.log("MOUNT", this.props); } componentWillUnmount() { console.log("UNMOUNT", this.props); } render() { return null; } }
Con el gancho useEffect
:
function Effect(props) { React.useEffect(() => { console.log("MOUNT", props); return () => console.log("UNMOUNT", props) }, []); return null; }
(Ejemplo completo: https://codesandbox.io/s/2oo7zqzx1n )
Esto no funciona, ya que la función de "limpieza" devuelta en useEffect
captura los accesorios tal como estaban durante el montaje y no el estado de los accesorios durante el desmontaje.
¿Cómo podría obtener la última versión de los accesorios en useEffect
clean up sin ejecutar el cuerpo de la función (o limpieza) en cada cambio de accesorio?
Una pregunta similar no aborda la parte de tener acceso a los accesorios más recientes.
Los documentos de reacción indican:
Si desea ejecutar un efecto y limpiarlo solo una vez (al montar y desmontar), puede pasar una matriz vacía ([]) como segundo argumento. Esto le dice a React que su efecto no depende de ningún valor de accesorios o estado, por lo que nunca necesita volver a ejecutarse.
En este caso, sin embargo, dependo de los accesorios... pero solo para la parte de limpieza...
Puede hacer uso de useRef y almacenar los accesorios que se utilizarán dentro de un cierre, como el método de devolución de llamada de devolución useEffect.
function Home(props) { const val = React.useRef(); React.useEffect( () => { val.current = props; }, [props] ); React.useEffect(() => { return () => { console.log(props, val.current); }; }, []); return <div>Home</div>; }
Sin embargo, una mejor manera es pasar el segundo argumento a useEffect
para que la limpieza y la inicialización ocurran en cualquier cambio de accesorios deseados.
React.useEffect(() => { return () => { console.log(props.current); }; }, [props.current]);
useLayoutEffect() es tu respuesta en 2021
useLayoutEffect(() => { return () => { // Your code here. } }, [])
Esto es equivalente a ComponentWillUnmount.
El 99% de las veces desea usar useEffect, pero si desea realizar alguna acción antes de desmontar el DOM, puede usar el código que proporcioné.
useLayoutEffect
es ideal para limpiar eventListeners en nodos DOM.
De lo contrario, con useEffect
será nulo en el momento en que se active el gancho
Más información sobre documentos de reacción https://reactjs.org/docs/hooks-reference.html#uselayouteffect
import React, { useLayoutEffect, useRef } from 'react'; const audioRef = useRef(null); useLayoutEffect(() => { if (!audioRef.current) return; const progressEvent = (e) => { setProgress(audioRef.current.currentTime); }; audioRef.current.addEventListener('timeupdate', progressEvent); return () => { try { audioRef.current.removeEventListener('timeupdate', progressEvent); } catch (e) { console.warn('could not removeEventListener on timeupdate'); } }; }, [audioRef.current]);
Adjuntar referencia al nodo DOM del componente
<audio ref={audioRef} />