Що робить useCallback()?
Що робить useCallback()
useCallback() - це хук, який мемоізує саму функцію,
тобто зберігає її посилання між рендерами,
щоб React не створював нову функцію щоразу,
якщо її залежності не змінилися.
Синтаксис
javascript
const memoizedCallback = useCallback(() => {
// код функції
}, [dependencies]);- Перший аргумент - функція, яку потрібно "запам'ятати".
- Другий аргумент - масив залежностей. Поки залежності не зміняться, React буде повертати одну й ту саму функцію.
Приклад без useCallback (не оптимізовано)
javascript
function App() {
const [count, setCount] = useState(0);
// При кожному рендері створюється нова функція
const handleClick = () => {
setCount(count + 1);
};
return <Button onClick={handleClick} />;
}Якщо Button обгорнутий у React.memo,
він все одно перерендерюватиметься,
тому що handleClick щоразу - нове посилання.
Приклад з useCallback (оптимізовано)
javascript
import { useState, useCallback } from "react";
function App() {
const [count, setCount] = useState(0);
// Функція перестворюється тільки при зміні count
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Button onClick={handleClick} />;
}
const Button = React.memo(({ onClick }) => {
console.log("Ререндер кнопки");
return <button onClick={onClick}>+</button>;
});Тепер handleClick не змінює посилання на кожному рендері,
і React.memo(Button) не перерендерюється без причини.
Що повертає useCallback()
useCallback() повертає ту саму функцію,
яку ти йому передав, але мемоізовану (зі збереженим посиланням).
Простіше кажучи:
javascript
useCallback(fn, deps)еквівалентно:
javascript
useMemo(() => fn, deps)Коли корисний useCallback()
| Ситуація | Чому використовувати |
|---|---|
| Передаєш функції в дочірні компоненти | Щоб не викликати їхній зайвий рендер |
Використовуєш useEffect або useMemo і хочеш стабільну залежність | Щоб ефект не спрацьовував щоразу |
| У компонентах, де обробник створюється всередині JSX | Щоб не перестворювати функцію при кожному рендері |
Приклад: стабілізація залежності в useEffect
javascript
function Example({ userId }) {
const fetchUser = useCallback(() => {
return fetch(`/api/user/${userId}`).then(r => r.json());
}, [userId]);
useEffect(() => {
fetchUser().then(console.log);
}, [fetchUser]); // не викликає нескінченний цикл
}Без useCallback, fetchUser створювалася б щоразу,
і useEffect викликався б нескінченно.
Важливо пам'ятати
| Правило | Пояснення |
|---|---|
useCallback не прискорює сам код | Він тільки запобігає зайвим перерендерам |
| Не варто використовувати всюди | Тільки якщо функція передається як проп або використовується в залежностях |
| Працює за посиланням | React порівнює не вміст функції, а її посилання в пам'яті |
Підсумок
| Питання | Відповідь |
|---|---|
Що робить useCallback() | Мемоізує (кешує) функцію, щоб не перестворювати її при кожному рендері |
| Коли перестворюється | Тільки якщо змінилися залежності |
| Що повертає | Стабільне (те саме) посилання на функцію |
| Коли використовувати | Коли функція передається в дочірній компонент або використовується в useEffect |
| Коли не потрібно | Якщо функція не впливає на перерендери або не використовується як залежність |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.