Ті з вас, хто дивились минулий етер зі співбесідою, мали бачити, як ми з Альбертом розмірковували над практичною задачею. І декому здалося, що я підштовхував його до не найкращого рішення цієї задачі. Так от, друзі. Вам не здалося.
І зараз чудовий час для мене визнати помилку та закріпити цей урок.
Тож, в чому проблема? Як виявилось, я дещо наплутав механізм роботи effect cleanup, а саме коли викликається та сама cleanup функція:
useEffect(() => {
// якась магія
return () => {
// знову прибирати за цими магами
};
}, [dep]);Так от, я чомусь був переконаний, що cleanup викличеться при знищенні, або ж unmount компонента. Очевидно, що це в корені невірно, адже ця функція викликатиметься щоразу, як зміняться залежності. Перед виконанням самого ефекту.
Чому ж я був такий впевнений в зворотному? Бо останнім часом не дуже то й писав ефекти як такі, а з cleanup і поготів. А якщо писав, то зазвичай ішлося про ініціалізаційні ефекти, що мають виконатися лише раз:
useEffect(() => {
// одноразова магія
return () => {
// разочок прибрав і все
};
}, []);І ось саме в цьому випадку cleanup функцію буде викликано лише один-єдиний раз — на unmount.
Давайте ще раз зафіксуємо:
useEffect(() => {
return () => {
// ОДИН раз на unmount
}
}, []); <- пусті залежності
useEffect(() => {
return () => {
// ЩОРАЗУ на зміну залежностей + ОДИН раз на unmount
}
}, [dep]); <- не пусті залежностіЩо цікаво, я не так давно досліджував, як саме працює сам useEffect, як ставляться в чергу ефекти, як реєструються хуки і чому не можна виклики хуків класти в умовні конструкції. А про механізм cleanup просто забув.
Якщо дуже коротко, це все впирається в масив залежностей. React на кожен ререндер перевіряє попередні залежності і нові (не сам масив, а саме залежності) і ставить в чергу ефект лише тоді, як хоча б одна залежність зміниться за значенням або посиланням. До речі, важливо памʼятати, що useEffect не виконує сам ефект, а лише відповідає за постановку його в чергу.
Тож так, беручи прикладу з етеру, нам дійсно не потрібні ніякі рефи, проміжні значення та інші ускладнення:
useEffect(() => {
const intervalId = setInterval(...);
return () => clearInterval(intervalId);
}, [userId]);Що ж, сподіваюсь, це нагадування стане в нагоді не лише мені самому, а я більше не морочитиму людям голову і не позоритимусь із тими ефектами на всю країну в прямому етері.
До речі, хто таки дивився останній випуск, чи винесли ви для себе щось корисне? Розкажіть хоч тут в коментарях, якщо на ютубі соромитесь ;)
@babichdev