React
Для чего модуль
Перейти от уровня «знаю хуки» к уровню «могу проектировать и защищать React-решение под production-нагрузку».
Результат после прохождения
- Вы понимаете, почему компонент ререндерился, и доказываете это через инструменты.
- Вы проектируете state-границы так, чтобы UI был предсказуемым и поддерживаемым.
- Вы избегаете типичных async/effect ошибок и stale-data багов.
- Вы связываете оптимизации с метриками UX, а не с «красивым кодом».
Термины и аббревиатуры
| Термин | Коротко |
|---|---|
Reconciliation | Сравнение virtual tree |
Hook | API React для логики |
Stale closure | Устаревшие значения в замыкании |
Memoization | Кэш вычислений/рендера |
Hydration | Активация клиентского UI |
Фокус по грейдам
Junior: понимать базовые механики и объяснять их простыми примерами.Middle: применять тему в продуктовых сценариях с учетом рисков и ограничений.Senior: управлять архитектурными trade-offs, метриками и эволюцией решения.
Как работать с модулем
- Каждый урок проходите через mini-case из реального экрана.
- Для каждого решения фиксируйте: симптом -> гипотеза -> замер -> изменение -> результат.
- Любую оптимизацию проверяйте profiler/метриками.
Программа модуля
Урок 1. Рендеринг и reconciliation
Цель: понимать рендер React как конкретную механику, а не «магический процесс».
Что происходит при обновлении
- React строит новое дерево элементов.
- Сравнивает с предыдущим (reconciliation).
- Применяет изменения в commit phase.
Ключевой вывод: оптимизировать нужно не «количество вызовов функций», а дорогие пересоздания/commit-операции.
key и стабильность идентичности
Нестабильный key (например, index в reorder-списке) приводит к remount и потере локального state.
{items.map((item) => (
<Row key={item.id} item={item} />
))}
Profiler: что смотреть
- Какие компоненты часто ререндерятся.
- Длительность render/commit.
- Почему ререндер произошел (props, state, parent render).
Где ломается в проде
- Использование
indexкакkeyв изменяемых списках. - Случайные remount из-за нестабильных ключей/условного дерева.
- «Оптимизация» без замера, которая усложняет код и не улучшает UX.
Мини-задача (обязательная)
Возьмите список с drag/reorder и сравните два варианта:
key=index и key=item.id.
Снимите profiler и объясните разницу в поведении и стоимости обновлений.
Что спросит интервьюер: почему компонент ререндерился и как вы это доказали.
Критерий готовности по уроку: вы можете объяснить любой ререндер через profiler-данные, а не через догадки.
Урок 2. Hooks и side effects
Цель: писать эффекты без гонок, утечек и скрытых зависимостей.
useEffect как синхронизация с внешним миром
Эффект нужен не «чтобы что-то выполнить после рендера», а чтобы синхронизироваться с внешним источником: сеть, подписки, таймеры, DOM APIs.
Зависимости и stale closures
Если зависимость не указана, эффект может читать устаревшие значения. Если зависимостей слишком много и они нестабильны, будет лишняя работа.
Асинхронные эффекты: cancel first
useEffect(() => {
const ac = new AbortController();
(async () => {
try {
const res = await fetch(`/api/search?q=${query}`, { signal: ac.signal });
const data = await res.json();
setItems(data.items);
} catch (e) {
if (e.name !== 'AbortError') setError(e);
}
})();
return () => ac.abort();
}, [query]);
Где ломается в проде
- Эффект с
[], который использует динамические значения. - Два параллельных запроса обновляют один state в неопределенном порядке.
- Cleanup отсутствует для подписки/таймера.
Мини-задача (обязательная)
Сделайте экран поиска с debounce + cancel предыдущего запроса. Зафиксируйте, как предотвращается stale UI.
Что спросит интервьюер:
когда массив зависимостей [] корректен, а когда это баг.
Критерий готовности по уроку: вы можете написать effect без race-condition и объяснить, почему он безопасен.
Урок 3. Управление состоянием
Цель: отделять local state, shared state и server state, чтобы не перегружать архитектуру.
State ownership
Главный вопрос: где должен жить источник истины.
- Локальный state - ближе к компоненту.
- Shared UI state - поднимаем на ближайший общий уровень.
- Server state - отдельные механизмы загрузки/кэширования/инвалидации.
Антипаттерн «глобальный store на все»
Проблемы:
- Сильная связанность модулей.
- Сложная отладка побочных эффектов.
- Ненужные ререндеры широких частей дерева.
Практика декомпозиции
Для сложного экрана выделяйте:
- State владения данными.
- State UI-представления.
- Derived data (мемоизируемое вычисление).
Где ломается в проде
- Дублирование одного и того же state в нескольких местах.
- Мутация объекта в store и «невидимые» изменения.
- Смешение server state и локального UI state.
Мини-задача (обязательная)
Возьмите экран фильтруемого каталога и разложите state по ownership: что локально, что shared, что server state, что derived.
Что спросит интервьюер:
когда Context достаточно, а когда нужен выделенный state-слой.
Критерий готовности по уроку: вы можете аргументированно описать state-архитектуру экрана и показать, где она защищает от регрессий.
Урок 4. Надежность и перформанс
Цель: проектировать UI, устойчивый к ошибкам, задержкам и частичным отказам.
Error boundaries и fail-safe UI
- Ошибка одного виджета не должна «ронять» весь экран.
- Пользователь должен получать внятный fallback, а не белый экран.
Loading/empty/error как часть контракта
Для каждого запроса заранее проектируйте 4 состояния: loading, success, empty, error. Это снижает количество «невидимых» багов на edge-cases.
Performance с привязкой к UX
- Сначала измеряем baseline.
- Оптимизируем конкретный bottleneck.
- Проверяем влияние на сценарий пользователя.
Где ломается в проде
- «Оптимизация» через
memo/useMemoбез эффекта на UX. - Отсутствие fallback при частичном падении API.
- Нет связи frontend ошибки с backend trace.
Мини-задача (обязательная)
Соберите perf-case: проблема рендера -> baseline -> изменение -> итоговый замер. Отдельно опишите error/fallback стратегию для этого экрана.
Что спросит интервьюер: почему ваша оптимизация реально улучшает UX, а не только «красиво выглядит в коде».
Критерий готовности по уроку: вы можете защитить React-решение через надежность и измеримый эффект на пользовательский сценарий.
Практика
- Разберите 12 вопросов: 8 из Middle JavaScript и React, 4 из Senior Frontend.
- Сделайте profiler-разбор одного реального экрана с фиксацией до/после.
- Реализуйте экран поиска с debounce + cancel + empty/error states.
- Подготовьте state ownership-карту сложного экрана.
- Зафиксируйте один reliability-case: partial API failure и поведение UI.
- Соберите сценарий loading/error/empty в Песочнице и проверьте устойчивость UI.
Связь с треками и вопросами
- Треки: Junior трек, Middle трек, Senior трек.
- Вопросы: Middle JavaScript и React, Senior Frontend.
- Повторение: 3-5 вопросов без подсказок -> сверка с модулем -> повтор через 24 часа.
Критерий готовности
Вы можете объяснить React-решение как инженерный кейс: контекст -> архитектурный выбор -> риски -> замеры -> результат.
Артефакты после модуля
- Profiler-отчет до/после по одному экрану.
- State ownership-документ для сложного UI.
- Набор из 8 сильных interview-ответов по React с примерами.
- Один reliability runbook для UI-инцидента.