Коли змінюється стан компонента, React перерендерює його і всіх нащадків. Перш ніж обгортати все в memo, варто змінити структуру - часто цього досить.
1. Опустити стан туди, де він потрібен (state colocation):
// було: введення в пошук перерендерює всю сторінку
function Page() {
const [query, setQuery] = useState('');
return (
<>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<Results query={query} />
<HeavySidebar /> {/* рендериться на кожну літеру */}
</>
);
}
// стало: стан живе в компоненті, якому він потрібен
function Search() {
const [query, setQuery] = useState('');
return (
<>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<Results query={query} />
</>
);
}
function Page() {
return (
<>
<Search />
<HeavySidebar /> {/* більше не залежить від введення */}
</>
);
}
2. Передати важкий вміст як children:
function Collapsible({ children }) {
const [open, setOpen] = useState(false);
return (
<section>
<button onClick={() => setOpen(!open)}>Розгорнути</button>
{open && children}
</section>
);
}
<Collapsible>
<HeavyChart />
</Collapsible>
Коли змінюється open, React перерендерює Collapsible, але children - це JSX, створений батьком, і він не змінився. HeavyChart не рендериться заново.
Інші принципи з документації React:
- не оновлювати стан в ефектах без потреби - ланцюжки «ефект встановлює стан - рендер - ефект» множать рендери;
- обчислювати похідні значення під час рендеру, а не зберігати копію в стані;
- прибирати зайві залежності ефектів - функції й об'єкти, створені в тілі компонента, змінюються на кожен рендер.
Рендер - не обов'язково проблема. Рендер - це виклик функції й порівняння результату; DOM змінюється лише там, де результат відрізняється. Оптимізувати варто тоді, коли профілювання показує помітні затримки, а не «про всяк випадок».
React Compiler автоматично додає мемоізацію, але структурні рішення лишаються корисними: чим менше компонентів залежить від стану, що часто змінюється, тим менше роботи взагалі.
Докладніше в документації: memo: чи варто додавати memo всюди