# React-архітектура на Senior-співбесіді: як аргументувати рішення

> Senior відрізняється не знанням API, а вмінням аргументувати: межі компонентів, вибір місця для стану, обробка помилок і формат «контекст → варіанти → вибір → ціна». З прикладами сильних і слабких відповідей.

- Автор: Юра Скиба (https://cookiesoftware.io)
- Опубліковано: 2026-09-24
- Категорія: React і Frontend
- Canonical: https://cookiesoftware.io/blog/senior-react-architecture

---

**Коротка відповідь.** На Senior-раунді перевіряють не «чи знаєш ти патерни», а чи вмієш ти обирати між ними і чесно називати ціну вибору. Сильна відповідь має структуру «контекст → варіанти → вибір → ціна». Слабка – це універсальний рецепт без умов застосування. Нижче – як мислити про межі компонентів, місце для стану й обробку помилок так, щоб це звучало як досвід, а не як конспект.

## Що насправді оцінюють на архітектурному раунді

Інтерв'юер ставить відкрите питання: «як би ти організував стан у великому застосунку?», «як структурувати компоненти фічі?». Правильної відповіді не існує – оцінюють процес:

- чи уточнюєш ти контекст перед відповіддю (розмір команди, вимоги, обмеження);
- чи бачиш більше одного варіанта;
- чи називаєш ціну свого вибору сам, до того як спитають;
- чи відрізняєш «так модно» від «так потрібно тут».

Формальний рівень компетенцій за грейдами я розбирав у статті [Middle → Senior Frontend](/blog/middle-to-senior-frontend) – тут зосередимось саме на аргументації.

## Межі компонентів і шарів

Базове архітектурне рішення в React – де провести межі. Робочий поділ на три шари:

1. **UI-компоненти** – рендерять пропси, не знають про API і бізнес-правила. Їх легко переносити й тестувати.
2. **Логіка** – хуки з бізнес-поведінкою: `useCart`, `useCheckoutForm`. Тут живуть правила, валідація, оркестрація запитів.
3. **Дані** – шар доступу до API: функції запитів, типи відповідей, серіалізація.

Сигнали порушених меж, які варто вміти називати: компонент на 400 рядків із fetch-ами всередині JSX; UI-компонент, що імпортує API-клієнт; бізнес-правило, продубльоване у трьох компонентах. Рефакторинг тут – не «розбити на менші файли», а винести причину зміни в один шар: правило змінюється в одному місці.

Важливий нюанс для співбесіди: поділ на шари – це інструмент, а не догма. Для одноразової фічі з одним екраном три шари можуть бути надлишковими, і сказати це вголос – плюс, а не мінус.

## Де жити стану: критерії, а не бібліотеки

Найчастіша помилка кандидатів – відповідати назвою бібліотеки. Сильніша відповідь – критерії вибору місця для стану:

| Тип стану | Де жити | Критерій |
|---|---|---|
| Локальний UI (відкритий дропдаун, значення інпута) | `useState` у компоненті | Ніхто інший його не читає |
| Спільний для гілки дерева | Піднятий до спільного предка або context | Читають кілька сусідів |
| Серверні дані (списки, профілі) | Кеш запитів (будь-яка бібліотека кешування або власний шар) | Джерело правди – сервер; потрібні refetch, інвалідація, статуси |
| Справді глобальний клієнтський (тема, auth-сесія) | Глобальний store або context на верхньому рівні | Читається скрізь, змінюється рідко |

Ключова теза, що відрізняє Senior: **серверні дані – не клієнтський стан.** Складати відповіді API у глобальний store і вручну синхронізувати – це відтворення кешу без інвалідації. Якою бібліотекою користуватись – деталь; розуміння, що це різні категорії стану, – суть.

## Помилки й loading як архітектурне рішення

Junior обробляє помилки в кожному компоненті окремо. Senior проєктує політику:

- **Межі помилок (error boundaries)** на рівні маршруту або великої фічі: падіння віджета не кладе всю сторінку.
- **Єдина семантика статусів**: кожен запит має явні loading / error / empty / success стани, і компоненти не вигадують їх щоразу заново.
- **Розділення відновлюваних і фатальних помилок**: 401 → редірект на логін; мережева помилка → retry із повідомленням; помилка рендера → boundary із fallback.

На співбесіді достатньо намалювати це словами: «на рівні маршруту – boundary, на рівні запитів – єдиний хук зі статусами, на рівні форм – локальна валідація». Це показує системне мислення краще за будь-який список бібліотек.

## Формат «контекст → варіанти → вибір → ціна»

Приклад повної аргументації на типове питання «винести логіку фільтрів у context чи тримати в компоненті?»:

- **Контекст:** фільтри читають три компоненти на одній сторінці; інші сторінки їх не використовують; команда – четверо людей.
- **Варіанти:** (1) підняти стан до спільного предка і передати пропсами; (2) локальний context сторінки; (3) глобальний store.
- **Вибір:** варіант 2 – context на рівні сторінки: споживачів більше двох, але стан не глобальний.
- **Ціна:** будь-яка зміна фільтрів рендерить усіх споживачів context; якщо з'явиться дорогий компонент-споживач, розіб'ю context на «значення» і «сеттери» або повернусь до пропсів.

Чотири речення – і інтерв'юер бачить усе: ти зважував альтернативи, обрав під контекст і знаєш слабке місце свого рішення заздалегідь.

## Слабкі vs сильні відповіді: приклади

**Питання: «Чому ти б використав глобальний store?»**

- Слабко: «Бо в великих проєктах завжди потрібен store, це стандарт».
- Сильно: «Якщо є справді глобальний клієнтський стан – сесія, тема, фіча-флаги. Для серверних даних store не потрібен: їх місце в кеші запитів. У поточному проєкті глобального стану в мене два поля, тож вистачає context».

**Питання: «Як ти організуєш структуру папок?»**

- Слабко: «components, hooks, utils, services – так усі роблять».
- Сильно: «Групую за фічами: усе, що змінюється разом, лежить поруч – компоненти, хуки й запити фічі в одній папці. Спільне виношу лише після другого-третього використання. Ціна: іноді складніше знайти, де межа фічі, тому домовляємось про правила імпортів між фічами».

Різниця не в знаннях – обидва кандидати знають однакові слова. Різниця в тому, що сильна відповідь прив'язана до умов і чесно називає ціну.

## Ще один повний приклад: форми

Друге за популярністю архітектурне питання після стану – «як ти працюєш із формами?». Той самий формат:

- **Контекст:** у застосунку і прості форми (логін, пошук), і складні (багатокрокове оформлення з залежними полями).
- **Варіанти:** (1) контрольовані інпути з ручним `useState` на кожне поле; (2) неконтрольовані поля + читання значень на submit; (3) бібліотека форм зі схемою валідації.
- **Вибір:** для простих форм – варіант 1 або 2, без залежностей; для складних – варіант 3, бо ручна синхронізація валідації, touched-станів і залежних полів швидко стає джерелом багів.
- **Ціна:** бібліотека – це залежність і її API, який треба знати всій команді; схема валідації дублюється з серверною, тому домовляємось про спільне джерело правди для правил.

Зверни увагу на структуру: рішення різне для різних частин застосунку. «Одна технологія на всі випадки» – маркер шаблонного мислення; диференціація за складністю – маркер досвіду.

## Червоні прапорці у відповідях

Фрази, які на Senior-раунді працюють проти тебе:

- «Так прийнято» / «це best practice» – без пояснення, чому practice став best і чи застосовний тут.
- «Ми завжди використовуємо X» – відсутність варіантів означає, що вибору не було.
- «Це масштабованіше» – без відповіді, яке саме зростання очікується і що конкретно зламається без цього рішення.
- Мовчання про недоліки власного вибору. Якщо ціну рішення першим називає інтерв'юер – ти її не бачив.

Дзеркальне правило: чесне «тут я б не ускладнював» на просте питання – сильна відповідь. Уміння НЕ застосувати патерн цінується не менше, ніж уміння застосувати.

## Як тренувати аргументацію

1. Візьми будь-яке своє минуле рішення (стан, структура, бібліотека) і письмово розклади за форматом «контекст → варіанти → вибір → ціна».
2. Зроби те саме для протилежного рішення – аргументуй, за яких умов правильним був би інший варіант. Якщо не виходить – ти не обирав, а слідував звичці.
3. Потренуйся вголос: архітектурні відповіді на письмі й у розмові – різні навички.

Продовження цієї теми в масштабі цілого застосунку – дизайн стрічки, кешування, продуктивність – розбираю в статті про [frontend system design](/blog/frontend-system-design-interview). А про те, коли оптимізація стає архітектурним питанням, – у матеріалі про [продуктивність React без передчасного useMemo](/blog/optymizatsiia-react-performance).
