Позвольте мне объяснить результат этого кода, чтобы легко задать мою проблему.
const ForExample = () => {
const [name, setName] = useState('');
const [username, setUsername] = useState('');
useEffect(() => {
console.info('effect');
console.info({
name,
username
});
return () => {
console.info('cleaned up');
console.info({
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(). (логирование "очищается" только на момент размонтирования компонента)
@Tholle Вы имеете в виду, что мне нужно сделать 2 отдельных метода useEffect ()?
Да, это один из способов сделать это.
@Tholle Я думал, что это будет переопределено последним методом useEffect(). Я попытаюсь. Спасибо
@ Толле Это работает. еще раз спасибо. Кстати, есть ли более красивый способ реализовать это? Такое ощущение, что мы дважды пишем одноимённые методы.
Здорово! Пожалуйста. Это зависит от того, что должна делать уборка. 2 отдельных эффекта - неплохое решение.
@Tholle для меня не работает, я работаю с редуксом, и у меня есть метод, который сбрасывает все данные, когда компонент выгружается, но у меня не работает, помогите......
@Racal Опубликуйте свой вопрос, уточните свою проблему с помощью некоторых кодов, позвоните мне с тегом, и, возможно, я смогу вам помочь.
@koo я решил эту проблему, но мы можем подружиться на github. Спасибо.





Поскольку очистка не зависит от username, вы можете поместить очистку в отдельный useEffect, которому в качестве второго аргумента передается пустой массив.
Пример
const { useState, useEffect } = React;
const ForExample = () => {
const [name, setName] = useState("");
const [username, setUsername] = useState("");
useEffect(
() => {
console.info("effect");
},
[username]
);
useEffect(() => {
return () => {
console.info("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, я не вижу этого триггера.
Вы можете использовать более одного useEffect().
Например, если моя переменная data1, я могу использовать все это в своем компоненте:
useEffect( () => console.info("mount"), [] );
useEffect( () => console.info("data1 update"), [ data1 ] );
useEffect( () => console.info("any update") );
useEffect( () => () => console.info("data1 update or unmount"), [ data1 ] );
useEffect( () => () => console.info("unmount"), [] );
в чем разница между первым и последним useEffects, первый useEffect будет вызываться для будетмонтировать или сделалмаунт, последний useEffect был возвращен функцией обратного вызова с пустым массивом, почему? Не могли бы вы уточнить каждый вариант использования useEffect, когда и как мы можем его использовать?
@siluverukirankumar Возвращаемое значение (функция) обратного вызова — это то, что вызывается при уничтожении (событии размонтирования). Вот почему последний пример — это HOC, немедленно возвращающий функцию. Второй параметр — это место, где React будет искать изменения для повторного запуска этого хука. Когда это пустой массив, он будет запускаться только один раз.
Спасибо, @Georgy понял, что последний useEffect возвращает обратный вызов, который не видно четко
Итак, если вы делаете хук useEffect, и он возвращает функцию... тогда код перед возвращаемой функцией запускается как componentDidMount... и код в возвращаемой функции вызывается для componentWillUnmount? Это немного сбивает с толку, поэтому убедитесь, что я правильно понимаю. useEffect(()=>{ // код для запуска при монтировании ... return()=> { // код для запуска при размонтировании}}) Верно?
Я предлагаю прочитать overreacted.io/a-complete-guide-to-useeffect Думать о хуках в жизненных циклах на самом деле не так уж и приятно.
Это приятно. Но я считаю, что ваш второй и третий useEffect должны читаться как «обновление», а не «обновление».
Очень классный ответ. Не знал об этом.
Это то, что я искал. Спасибо друг
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, не позволяющее приложению устанавливать состояние после размонтирования компонента.
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
useEffect изолированы в своей собственной области видимости и соответственно отображаются. Изображение из https://reactjs.org/docs/hooks-custom.html

Ссылка на решение приветствуется, но убедитесь, что ваш ответ полезен и без нее: добавить контекст вокруг ссылки, чтобы ваши коллеги-пользователи имели некоторое представление о том, что это такое и почему оно существует, а затем процитируйте наиболее важную часть страницы, на которую вы ссылаетесь, в если целевая страница недоступна. Ответы, которые представляют собой чуть больше ссылки, могут быть удалены.
вместо того, чтобы создавать слишком много сложных функций и методов, я создаю прослушиватель событий и автоматически выполняю монтирование и размонтирование, не беспокоясь о том, чтобы делать это вручную. Вот пример.
//componentDidMount
useEffect( () => {
window.addEventListener("load", pageLoad);
//component will unmount
return () => {
window.removeEventListener("load", pageLoad);
}
});
теперь, когда эта часть выполнена, я просто запускаю все, что хочу, из функции pageLoad, как это.
const pageLoad = () =>{
console.info(I was mounted and unmounted automatically :D)}
Чтобы добавить к принятому ответу, у меня была аналогичная проблема, и я решил ее, используя аналогичный подход с надуманным примером ниже. В этом случае мне нужно было зарегистрировать некоторые параметры componentWillUnmount, и, как описано в исходном вопросе, я не хотел, чтобы он регистрировался каждый раз, когда параметры изменялись.
const componentWillUnmount = useRef(false)
// This is componentWillUnmount
useEffect(() => {
return () => {
componentWillUnmount.current = true
}
}, [])
useEffect(() => {
return () => {
// This line only evaluates to true after the componentWillUnmount happens
if (componentWillUnmount.current) {
console.info(params)
}
}
}, [params]) // This dependency guarantees that when the componentWillUnmount fires it will log the latest params
Порядок использования эффектов имеет значение, если кому-то еще было интересно
Используя пользовательские события js, вы можете эмулировать размонтирование компонентаWillUnmount даже при наличии зависимости.
Проблема:
useEffect(() => {
//Dependent Code
return () => {
// Desired to perform action on unmount only 'componentWillUnmount'
// But it does not
if (somethingChanged){
// Perform an Action only if something changed
}
}
},[somethingChanged]);
Решение:
// Rewrite this code to arrange emulate this behaviour
// Decoupling using events
useEffect( () => {
return () => {
// Executed only when component unmounts,
let e = new Event("componentUnmount");
document.dispatchEvent(e);
}
}, []);
useEffect( () => {
function doOnUnmount(){
if (somethingChanged){
// Perform an Action only if something changed
}
}
document.addEventListener("componentUnmount",doOnUnmount);
return () => {
// This is done whenever value of somethingChanged changes
document.removeEventListener("componentUnmount",doOnUnmount);
}
}, [somethingChanged])
Предостережения:использованиеЭффекты должны быть в порядке, использованиеЭффект без зависимости должны быть записаны раньше, чтобы избежать вызова события после его удаления.
Наиболее важной частью этого ответа является предостережение о том, что вы должны использовать хуки useEffect, чтобы
У вас может быть 2 отдельных эффекта. Один, которому дается массив с
usernameв качестве второго аргумента, и тот, которому дается пустой массив в качестве второго аргумента.