Ответ
Ответ не найден
Ответ 18+ 🔞
А, ну это же про ту самую хуйню с useEffect и зависимостями, да? Ёпта, история старая, как мир, но каждый раз кто-то на неё наступает, как слепой кот на грабли.
Смотри, в чём суть. Представь, ты написал компонент, который должен загружать данные пользователя по его userId. И пишешь ты такую пиздопроебибну:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, []); // <-- Вот этот пустой массив, ёб твою мать!
}
И сидишь такой довольный, типа "работает". А потом меняешь userId, а данные-то не обновляются! Сам от себя охуел. Начинаешь искать баг в бэкенде, в сети, в чём угодно, только не в своём коде. А проблема-то в том, что ты залупе конской сказал эффекту: "Запустись один раз при монтировании и больше не еби мозг". Он так и делает. userId поменялся, а твой эффект про это нихуя не знает, он уже отработал и спит.
Вот тебе правильный вариант, чтобы не быть распиздяем:
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, [userId]); // <-- Вот теперь эффект будет срабатывать при КАЖДОМ изменении userId
Теперь логика простая: userId изменился -> старый эффект чистится -> запускается новый с актуальным айдишником. Всё, магия, пизда рулю.
Но тут есть другая крайность. Некоторые умники начинают пихать в массив зависимостей всё подряд, включая стейты и функции, которые создаются при каждом рендере. Получается манда с ушами: эффект начинает срабатывать после каждого обновления компонента, ты получаешь бесконечные запросы или вообще петлю ререндеров. Будет вам хиросима и нигерсраки, в общем.
function MyComponent() {
const [data, setData] = useState(null);
const [query, setQuery] = useState('');
const fetchData = () => { // Эта функция создаётся заново при КАЖДОМ рендере!
fetch(`/api/search?q=${query}`).then(r => r.json()).then(setData);
};
useEffect(() => {
fetchData();
}, [fetchData]); // Значит, этот эффект будет запускаться тоже при каждом рендере. Пиздец.
}
Что делать? Э, бошка, думай! Либо выноси функцию вне эффекта и мемоизируй её через useCallback, чтобы её ссылка не менялась без необходимости, либо вообще объявляй функцию внутри самого эффекта, если она используется только там.
// Вариант 1: Объявить функцию внутри эффекта
useEffect(() => {
const fetchData = () => {
fetch(`/api/search?q=${query}`).then(r => r.json()).then(setData);
};
fetchData();
}, [query]); // Зависит только от query
// Вариант 2: useCallback
const fetchData = useCallback(() => {
fetch(`/api/search?q=${query}`).then(r => r.json()).then(setData);
}, [query]); // Функция пересоздаётся только когда меняется query
useEffect(() => {
fetchData();
}, [fetchData]);
Главное правило — доверия ебать ноль к самому себе. Каждый раз, когда пишешь useEffect, спроси: "А нахуя я сюда этот userId засунул? А не забыл ли я вот эту переменную, от которой эффект реально зависит? А не положил ли я сюда что-то лишнее, из-за чего он будет срабатывать как сумасшедший?"
Если будешь так делать, то твой код не накроется медным тазом в самый неподходящий момент. Всё просто, как три копейки.