Pozwólcie, że wyjaśnię wynik tego kodu, aby łatwo zadać mój problem.
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>
);
};
Po ForExample component
zamontowaniu zostanie zarejestrowany „efekt”. Jest to związane z componentDidMount()
.
Za każdym razem, gdy zmienię dane wejściowe, zarówno „efekt”, jak i „wyczyszczony” będą rejestrowane. I odwrotnie, żadna wiadomość nie zostanie zarejestrowana za każdym razem, gdy zmienię nazwę użytkownika, ponieważ dodałem [username]
drugi parametr useEffect()
. Jest to związane zcomponentDidUpdate()
Na koniec, gdy ForExample component
odmontowanie zostanie zapisane, zostanie zapisane polecenie „wyczyszczone”. Jest to związane z componentWillUnmount()
.
Wszyscy to wiemy.
Podsumowując, funkcja „wyczyszczona” jest wywoływana za każdym razem, gdy komponent jest ponownie renderowany (obejmuje odmontowanie)
Jeśli chcę, aby ten komponent rejestrował się „wyczyszczony” tylko na moment, w którym jest odmontowywany, wystarczy zmienić drugi parametr useEffect()
na []
.
Ale jeśli zmienię [username]
na []
, ForExample component
nie implementuje już componentDidUpdate()
danych wejściowych dla nazwy.
Chcę to zrobić, aby komponent obsługiwał zarówno componentDidUpdate()
tylko wprowadzanie nazwy, jak i componentWillUnmount()
. (rejestrowanie `` wyczyszczone '' tylko na moment, w którym komponent jest odmontowywany)
źródło
username
w której jako drugi argument, i jedna, której jako drugi argument podano pustą tablicę.Odpowiedzi:
Ponieważ czyszczenie nie jest zależne od opcji
username
, możesz umieścić czyszczenie w oddzielnym,useEffect
który otrzymuje pustą tablicę jako drugi argument.Przykład
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>
źródło
możesz użyć więcej niż jednego useEffect
na przykład, jeśli moja zmienna to data1, mogę użyć tego wszystkiego w moim komponencie
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"), [] );
źródło
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> ) }
W powyższym kodzie funkcja fetchLegos zwraca obietnicę. Możemy „anulować” obietnicę, posiadając warunek w zakresie useEffect, uniemożliwiający aplikacji ustawienie stanu po odmontowaniu komponentu.
źródło
Zamiast tworzyć zbyt wiele skomplikowanych funkcji i metod, tworzę odbiornik zdarzeń i automatycznie wykonuję montowanie i odmontowywanie, bez martwienia się o zrobienie tego ręcznie. Oto przykład.
//componentDidMount useEffect( () => { window.addEventListener("load", pageLoad); //component will unmount return () => { window.removeEventListener("load", pageLoad); } });
teraz, gdy ta część jest skończona, po prostu uruchamiam wszystko, co chcę, z funkcji pageLoad w ten sposób.
const pageLoad = () =>{ console.log(I was mounted and unmounted automatically :D)}
źródło
useEffect są izolowane we własnym zakresie i odpowiednio renderowane. Obraz z https://reactjs.org/docs/hooks-custom.html
źródło