Що робить useMemo()?
Що робить useMemo()
Хук useMemo() запам'ятовує (кешує) результат обчислення функції
і повторно використовує його, якщо залежності не змінилися.
Простіше кажучи:
useMemoпотрібен, щоб не переобчислювати щось важке при кожному рендері, якщо вхідні дані не змінилися.
Синтаксис
javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);- Перший аргумент - функція, що повертає обчислюване значення.
- Другий аргумент - масив залежностей.
- React запам'ятовує результат цієї функції і переобчислить його лише тоді,
коли зміниться хоча б одна із залежностей
[a, b].
Простий приклад
javascript
import { useMemo, useState } from "react";
function Example() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
const expensiveCalculation = (num) => {
console.log("Виконується важкий розрахунок...");
let result = 0;
for (let i = 0; i < 1e7; i++) {
result += num * 2;
}
return result;
};
// useMemo запам'ятовує результат
const result = useMemo(() => expensiveCalculation(count), [count]);
return (
<div>
<p>Результат: {result}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<input value={text} onChange={(e) => setText(e.target.value)} />
</div>
);
}Що відбудеться:
- "Важкий розрахунок" (
expensiveCalculation) виконується лише тоді, коли змінюєтьсяcount. - Зміна
textне переобчислюєresult. - Це економить продуктивність при частих рендерах.
Приклад без useMemo (погано)
Якщо прибрати useMemo:
javascript
const result = expensiveCalculation(count);Кожен рендер, навіть при зміні text, буде викликати expensiveCalculation() заново,
навіть якщо count не змінювався.
Коли корисний useMemo
| Ситуація | Приклад |
|---|---|
| Важкі обчислення | сортування, фільтрація, великі цикли |
| Обчислення похідних даних | наприклад, фільтрувати список користувачів за пошуком |
| Оптимізація рендерів дочірніх компонентів | щоб не передавати новий об'єкт при кожному рендері |
Приклад: запобігаємо непотрібним рендерам
javascript
function Parent({ users }) {
const [filter, setFilter] = useState("");
// Без useMemo: новий масив створюється при кожному рендері
// З useMemo: створюється тільки при зміні users або filter
const filtered = useMemo(
() => users.filter((u) => u.name.includes(filter)),
[users, filter]
);
return <UserList users={filtered} />;
}Якщо UserList обгорнутий у React.memo,
він не перерендериться, поки filtered не зміниться.
Важливо
| Особливість | Пояснення |
|---|---|
useMemo кешує результат функції, а не саму функцію | Для функцій - використовуй useCallback |
| Використовуй тільки для справді дорогих обчислень | Не варто "обгортати все підряд" |
| Працює тільки при незмінних залежностях | Якщо хоча б одна змінилася - переобчислення заново |
Різниця між useMemo і useCallback
| Хук | Що кешує | Повертає |
|---|---|---|
useMemo | результат функції | значення |
useCallback | саму функцію | функцію |
Приклад:
javascript
const value = useMemo(() => compute(), [deps]);
const fn = useCallback(() => doSomething(), [deps]);Підсумок
| Питання | Відповідь |
|---|---|
Що робить useMemo() | Кешує результат функції, щоб не переобчислювати при кожному рендері |
| Коли переобчислює | Коли змінюється хоча б одна залежність |
| Що повертає | Збережене (мемоізоване) значення |
| Навіщо потрібен | Для оптимізації важких обчислень і запобігання непотрібним ререндерам |
| Не плутати з | useCallback (він кешує саму функцію) |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.