Permítanme explicar el resultado de este código para preguntar mi problema fácilmente.
const ForExample = () => {
const [name, setName] = useState('');
const [username, setUsername] = useState('');
useEffect(() => {
console.log('effect');
console.log({
name,
username
});
return () => {
console.log('cleaned up');
console.log({
name,
username
});
};
}, [username]);
const handleName = e => {
const { value } = e.target;
setName(value);
};
const handleUsername = e => {
const { value } = e.target;
setUsername(value);
};
return (
<div>
<div>
<input value={name} onChange={handleName} />
<input value={username} onChange={handleUsername} />
</div>
<div>
<div>
<span>{name}</span>
</div>
<div>
<span>{username}</span>
</div>
</div>
</div>
);
};
Cuando se ForExample component
monte, se registrará el 'efecto'. Esto está relacionado con el componentDidMount()
.
Y cada vez que cambio la entrada de nombre, se registrarán tanto el 'efecto' como la 'limpieza'. Viceversa, no se registrará ningún mensaje cada vez que cambie la entrada del nombre de usuario desde que agregué [username]
al segundo parámetro de useEffect()
. Esto está relacionado con lacomponentDidUpdate()
Por último, cuando se ForExample component
desmonte, se registrará 'limpiado'. Esto está relacionado con el componentWillUnmount()
.
Todos sabemos eso.
En resumen, se invoca 'limpiado' cada vez que el componente se vuelve a renderizar (incluye desmontar)
Si quiero que este componente se registre 'limpiado' solo en el momento en que se desmonte, solo tengo que cambiar el segundo parámetro de useEffect()
a []
.
Pero si cambio [username]
a []
, ForExample component
ya no implementa la componentDidUpdate()
entrada de nombre.
Lo que quiero hacer es que, para que el componente admita componentDidUpdate()
solo para la entrada de nombre y componentWillUnmount()
. (registro 'limpiado' solo en el momento en que se desmonta el componente)
fuente
username
como segundo argumento, y uno al que se le da una matriz vacía como segundo argumento.Respuestas:
Dado que la limpieza no depende de
username
, puede poner la limpieza en un lugar separadouseEffect
que reciba una matriz vacía como segundo argumento.Ejemplo
const { useState, useEffect } = React; const ForExample = () => { const [name, setName] = useState(""); const [username, setUsername] = useState(""); useEffect( () => { console.log("effect"); }, [username] ); useEffect(() => { return () => { console.log("cleaned up"); }; }, []); const handleName = e => { const { value } = e.target; setName(value); }; const handleUsername = e => { const { value } = e.target; setUsername(value); }; return ( <div> <div> <input value={name} onChange={handleName} /> <input value={username} onChange={handleUsername} /> </div> <div> <div> <span>{name}</span> </div> <div> <span>{username}</span> </div> </div> </div> ); }; function App() { const [shouldRender, setShouldRender] = useState(true); useEffect(() => { setTimeout(() => { setShouldRender(false); }, 5000); }, []); return shouldRender ? <ForExample /> : null; } ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>
fuente
puede utilizar más de un efecto de uso
por ejemplo, si mi variable es data1, puedo usar todo esto en mi componente
useEffect( () => console.log("mount"), [] ); useEffect( () => console.log("will update data1"), [ data1 ] ); useEffect( () => console.log("will update any") ); useEffect( () => () => console.log("will update data1 or unmount"), [ data1 ] ); useEffect( () => () => console.log("unmount"), [] );
fuente
function LegoComponent() { const [lego, setLegos] = React.useState([]) React.useEffect(() => { let isSubscribed = true fetchLegos().then( legos=> { if (isSubscribed) { setLegos(legos) } }) return () => isSubscribed = false }, []); return ( <ul> {legos.map(lego=> <li>{lego}</li>)} </ul> ) }
En el código anterior, la función fetchLegos devuelve una promesa. Podemos "cancelar" la promesa al tener un condicional en el alcance de useEffect, evitando que la aplicación establezca el estado después de que el componente se haya desmontado.
fuente
useEffect se aíslan dentro de su propio ámbito y se representan en consecuencia. Imagen de https://reactjs.org/docs/hooks-custom.html
fuente
en lugar de crear demasiadas funciones y métodos complicados, lo que hago es crear un detector de eventos y automáticamente hago el montaje y desmontaje sin tener que preocuparme por hacerlo manualmente. Aquí hay un ejemplo.
//componentDidMount useEffect( () => { window.addEventListener("load", pageLoad); //component will unmount return () => { window.removeEventListener("load", pageLoad); } });
ahora que esta parte está hecha, simplemente ejecuto todo lo que quiera desde la función pageLoad de esta manera.
const pageLoad = () =>{ console.log(I was mounted and unmounted automatically :D)}
fuente