Що робить useCallback()?
Що робить useCallback()
useCallback() - це хук мемоізації функцій.
Він повертає ту саму функцію (за посиланням) між рендерами,
якщо залежності не змінилися.
Синтаксис:
const memoizedCallback = useCallback(callback, [deps]);callback- сама функція, яку ти хочеш "запам'ятати".[deps]- масив залежностей, від яких залежить ця функція.
Приклад без useCallback
function App() {
const handleClick = () => console.log('click');
return <Button onClick={handleClick} />;
}Щоразу, коли компонент App ререндериться,
React створює нову функцію handleClick.
Навіть якщо логіка всередині не змінилася - посилання інше.
Якщо Button мемоізований (React.memo),
React подумає:
«Проп
onClickзмінився (нове посилання) - потрібно ререндерити дитину.»
Підсумок: Button зайвий ререндер.
З useCallback
function App() {
const handleClick = useCallback(() => console.log('click'), []);
return <Button onClick={handleClick} />;
}Тепер:
handleClickстворюється один раз;- При наступному рендері React поверне те саме посилання (якщо залежності не змінилися);
- Для дочірнього
React.memo-компонента пропonClickне змінився; - -> дочірній компонент не ререндериться.
Як це працює "під капотом"
React зберігає "стару" версію функції в пам'яті. При наступному рендері:
- Порівнює залежності
[deps]; - Якщо нічого не змінилося, повертає старе посилання на функцію з пам'яті;
- Якщо хоча б одна залежність змінилася - створює нову функцію і запам'ятовує її.
Приклад наочно
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('clicked');
}, []); // залежності порожні -> посилання стабільне
console.log('Parent render');
return (
<>
<Child onClick={handleClick} />
<button onClick={() => setCount(c => c + 1)}>+</button>
</>
);
}
const Child = React.memo(({ onClick }) => {
console.log('Child render');
return <button onClick={onClick}>Child</button>;
});Без useCallback:
Parent render
Child render
Parent render
Child render (зайвий)З useCallback:
Parent render
Child render
Parent render (Child не ререндериться)Коли useCallback реально допомагає
Використовуй, якщо:
- Колбек передається в мемоізований дочірній компонент (
React.memo,useMemoтощо); - Колбек бере участь у залежностях іншого
useEffect/useMemo, і ти хочеш уникнути хибних перезапусків.
Коли useCallback не потрібен
- Якщо функція використовується тільки всередині компонента (у JSX не передається в дочірні).
- Якщо дитина не мемоізована (
React.memoнемає). - Якщо компонент і так ререндериться завжди (наприклад, у батька немає оптимізації).
useCallbackне пришвидшує виконання функції. Він лише зберігає посилання, щоб React не думав, що вона "нова".
Паралель з useMemo
| Хук | Що кешує | Повертає |
|---|---|---|
useMemo(fn, deps) | результат обчислення | значення |
useCallback(fn, deps) | саму функцію | функцію |
Приклад еквівалентності:
useCallback(fn, deps) ≡ useMemo(() => fn, deps);Часті неточності у використанні
Невірні залежності: Якщо ти не додаси залежності, React буде використовувати застарілі дані із замикання.
// залежність count не вказана -> замикання
const onClick = useCallback(() => console.log(count), []);Правильно:
const onClick = useCallback(() => console.log(count), [count]);Підсумок
Що робить useCallback | Як допомагає |
|---|---|
| Кешує функцію між рендерами | Уникає зайвого створення функцій |
| Повертає те саме посилання, якщо залежності не змінилися | Пропси у дочірніх компонентів не "змінюються" |
Працює в парі з React.memo | Дозволяє реально уникнути ререндеру дитини |
| Не пришвидшує код, не зменшує навантаження на CPU | Тільки стабілізує посилання |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.