Позвольте мне объяснить результат этого кода, чтобы легко задать мою проблему.
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>
);
};
Когда ForExample component
монтируется, «эффект» будет зарегистрирован. Это связано с componentDidMount()
.
И всякий раз, когда я изменяю ввод имени, будут регистрироваться и «эффект», и «очищено». И наоборот, при изменении имени пользователя сообщение не будет регистрироваться, поскольку я добавил [username]
второй параметр useEffect()
. Это связано сcomponentDidUpdate()
Наконец, при ForExample component
размонтировании будет зарегистрировано «очищено». Это связано с componentWillUnmount()
.
Мы все это знаем.
Подводя итог, «очищено» вызывается всякий раз, когда компонент повторно отрисовывается (включая размонтирование).
Если я хочу, чтобы этот компонент регистрировал `` очищенный '' только на тот момент, когда он отключен, мне просто нужно изменить второй параметр useEffect()
на[]
.
Но если я перейду [username]
на []
, ForExample component
больше не будет реализовыватьcomponentDidUpdate()
ввод имени.
Я хочу сделать так, чтобы компонент поддерживал как componentDidUpdate()
ввод имени, так и componentWillUnmount()
. (ведение журнала `` очищено '' только для момента размонтирования компонента)
username
в нем второй аргумент, а другой - пустой массив, в качестве второго аргумента.Ответы:
Поскольку очистка не зависит от
username
, вы можете поместить очистку в отдельный,useEffect
которому в качестве второго аргумента предоставляется пустой массив.пример
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>
источник
вы можете использовать более одного useEffect
например, если моя переменная - data1, я могу использовать все это в своем компоненте
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"), [] );
источник
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> ) }
В приведенном выше коде функция fetchLegos возвращает обещание. Мы можем «отменить» обещание, добавив в область useEffect условие, не позволяющее приложению устанавливать состояние после размонтирования компонента.
источник
вместо того, чтобы создавать слишком много сложных функций и методов, я создаю прослушиватель событий и автоматически выполняю монтирование и размонтирование, не беспокоясь об этом вручную. Вот пример.
//componentDidMount useEffect( () => { window.addEventListener("load", pageLoad); //component will unmount return () => { window.removeEventListener("load", pageLoad); } });
Теперь, когда эта часть сделана, я просто запускаю все, что захочу, из функции pageLoad вот так.
const pageLoad = () =>{ console.log(I was mounted and unmounted automatically :D)}
источник
useEffect изолированы в пределах своей собственной области видимости и обрабатываются соответствующим образом. Изображение с https://reactjs.org/docs/hooks-custom.html
источник