Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Коли використовувати useCallback()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Хук `useCallback()` потрібен **не для прискорення функції**, а для того, щоб **зберігати одне й те саме посилання на функцію** між рендерами. **Ключове:** без масиву залежностей `useCallback` буде пересоздавати функцію на кожному рендері, тобто ніякої мемоізації не відбудеться.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коли використовувати `useCallback()` Хук `useCallback()` потрібен **не для прискорення функції**, а для того, щоб **зберігати одне й те саме посилання на функцію** між рендерами. Це важливо, коли: 1. **Функція передається в дочірній компонент**, особливо якщо він обгорнутий у `React.memo`. 2. **Функція використовується в** `useEffect` **/** `useMemo` і повинна залишатися стабільною (щоб не викликати ефект заново). 3. Ти хочеш уникнути **зайвого пересоздання функцій** при кожному рендері (що призводить до непотрібних перемальовувань). --- ### Приклад 1: передача функції в `React.memo`-компонент ```javascript const Button = React.memo(({ onClick }) => { console.log("Ререндер кнопки"); return <button onClick={onClick}>+</button>; }); function Counter() { const [count, setCount] = useState(0); // Без useCallback → при кожному рендері створюється нова функція const increment = useCallback(() => setCount(c => c + 1), []); return ( <div> <p>{count}</p> <Button onClick={increment} /> </div> ); } ``` Тут: - `increment` створюється **один раз**, оскільки залежності - `[]`. - Кнопка не перерендерюється без причини. Без `useCallback` `Button` ререндерилась би при кожній зміні `count`. --- ### Приклад 2: стабільна залежність у `useEffect` ```javascript function FetchUser({ id }) { const fetchUser = useCallback(() => { return fetch(`/api/user/${id}`).then(res => res.json()); }, [id]); useEffect(() => { fetchUser(); }, [fetchUser]); // useEffect викличеться тільки при зміні id } ``` Без `useCallback` `fetchUser` пересоздавалась би кожен рендер, і `useEffect` викликався б **кожного разу** - навіть якщо `id` не змінився. --- ## Підсумок - коли реально варто використовувати | Ситуація | Чи варто використовувати? | Чому | |---|---|---| | Передаєш функцію в `React.memo` компонент | Так | Уникаєш зайвих ререндерів | | Використовуєш функцію в `useEffect` / `useMemo` | Так | Стабілізуєш залежність | | Виклик функції прямо всередині JSX | Ні | Немає сенсу, вона не зберігається | | Функція не залежить від пропсів чи стану | Можна з `[]` | Створиться тільки один раз | | Легка функція, що не впливає на інших | Ні | Оптимізація не виправдана | --- ## Що станеться, якщо не вказати залежності ```javascript const memoizedFn = useCallback(() => { doSomething(a, b); }); ``` **Без масиву залежностей**: - `useCallback` буде пересоздавати функцію **на кожному рендері** - тобто **ніякої мемоізації не відбудеться**. - Це еквівалентно простому написанню: ```javascript const memoizedFn = () => doSomething(a, b); ``` Щоб `useCallback` працював, потрібно передати залежності, за якими React розумітиме, **коли функція дійсно повинна оновитися**. --- ## Приклад із залежностями ```javascript const handleClick = useCallback(() => { console.log(count); }, [count]); ``` - Функція пересоздається **тільки** якщо змінився `count`. - Якби ти не вказав `[count]`, то всередині функції завжди був би "заморожений" `count` з першого рендера. --- ## Важливо пам'ятати | Правило | Пояснення | |---|---| | `useCallback(fn, deps)` кешує посилання на функцію | Функція створюється заново тільки при зміні залежностей | | Якщо пропустити залежності | Функція буде пересоздаватися при кожному рендері (мемоізація не працює) | | Якщо поставити `[]` | Функція створюється один раз при монтуванні і ніколи не оновлюється | | Вказуй усі значення, що використовуються всередині | Інакше замикання міститиме застарілі дані | --- ## Підсумок | Питання | Відповідь | |---|---| | Коли використовувати `useCallback()` | Коли потрібно, щоб функція зберігала посилання між рендерами (React.memo, useEffect, useMemo) | | Що станеться без залежностей | Функція буде пересоздаватися кожен рендер - мемоізація не працює | | Що буде з `[]` | Функція створиться один раз і ніколи не оновиться | | Що повертає | Ту саму функцію, але з мемоізованим посиланням |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.