Вы замечали, как приложение начинает «тормозить» при увеличении количества компонентов? Частая причина — неоптимальное управление состоянием. Две популярные технологии (Redux и Context API) часто используются как взаимозаменяемые, но их некорректное применение ведёт к лавине ререндеров. Рассмотрим, как избежать типовых ошибок и выбрать правильный инструмент.
Redux vs Context API: не конкуренты, а разные инструменты
Когда Context API достаточно
Создайте контекст для статичных данных или низкоуровневых API:
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
Однако при частом обновлении контекста все потребители перерисовываются – независимо от того, изменились ли нужные им данные. В приложении с 50 компонентами, подписанными на контекст, изменение одного значения вызовет 50 ререндеров.
Когда требуется Redux
Для сложной бизнес-логики с частыми обновлениями используйте Redux с селекторами:
const selectUserDetails = state => state.user.details;
const selectOrders = createSelector(
[selectUserDetails],
(user) => user.orders.filter(order => !order.archived)
);
Redux Toolkit автоматически генерирует экшены и включает Immer для иммутабельных обновлений. Но плата за это — бойлерплейт, который окупается только в крупных проектах.
Анатомия лишних рендеров: четыре уровня оптимизации
- React.memo для тяжёлых компонентов
const UserCard = React.memo(({ user }) => {
// Рендер только при изменении пропсов
});
Но следите за сложностью пропсов: объекты и массивы требуют мемоизации.
- Контроль зависимостей с useMemo/useCallback
const formattedUsers = useMemo(() =>
users.map(u => ({ ...u, name: u.name.toUpperCase() })),
[users]);
- Слоистая архитектура состояний Разделите глобальное состояние на:
- Серверное состояние (React Query, SWR)
- UI состояние (Redux)
- Локальное состояние (useState)
- Профилирование через React DevTools Используйте «Highlight updates» для визуализации ререндеров. Замеры в React Profiler показывают узкие места точнее, чем интуиция.
Парадокс оптимизации: когда не нужно оптимизировать
Микрооптимизации часто дают обратный эффект. Преждевременная мемоизация усложняет код без метрик. Правильный подход:
- Собирайте перфоманс-бюджет (Lighthouse)
- Оптимизируйте только узкие места
- Используйте Suspense для ленивой загрузки
- Для анимаций применяйте CSS-решения вместо JS
Итоговый чеклист
✅ Context API — для редких обновлений (темы, локализация) ✅ Redux — для бизнес-логики с частыми изменениями ✅ React Query — для синхронизации с сервером ✅ Мемоизация — только для измеренных узких мест ✅ Многоуровневое состояние — разделять по ответственности
Производительность — не самоцель, а баланс между скоростью и сложностью кода. Иногда лучше позволить небольшой избыточный ререндер, чем превратить код в лабиринт мемоизации. Используйте метрики, а не догадки — только так можно принимать взвешенные решения.