Посібник з інтерв’ю в React: хуки, відображення та що запитують великі компанії
Віртуальний DOM, підводні камені хуків, продуктивність, управління станом, React 18, вправи з прямого кодування та способи пояснення причин повторного відрендерування.
Під час співбесід з React у великих компаніях рідко оцінюють знання тексту документації. Вони оцінюють те, чи розумієте ви, що відбувається на рівні алгоритмів — чому компонент перерисовується, чому ефект виконується двічі, чому оновлення стану не з’являється миттєво. Кандидати, які можуть пояснити чому, перемагають тих, хто знає лише як.
Нижче наведено типові теми, які насправді зустрічаються: основи, хуками, продуктивність, шаблони та несподівані запитання, які з’являються скрізь.
1. Основи
Запитання для розігріву майже завжди стосуються:
- Віртуальний DOM — що це таке та чому оновлення відбуваються швидше (використання алгоритмів diff/reconcile замість прямих записів у DOM).
- Примирення даних — як React вибирає, що оновити (перевірка ключів, типу елемента).
- JSX — формат, який компілюється у
React.createElement(); це потрібно добре знати.
value + onChange); неконтрольовані читають DOM через refs.Хитрий запитання: «Чому не використовувати індекс масиву як ключ?» Відповідайте конкретним прикладом переупорядкування/додавання елементів, коли React прив’язує стан до неправильного елемента.
2. Hooks (найоб’ємніша частина інтерв’ю)
useState
- Оновлення відбуваються асинхронно/пакетно.
- Застарілі закриття: кілька викликів
setCount(count + 1)у одній події ділять один і той самийcount;setCount(prev => prev + 1)вирішує цю проблему.
useEffect
- Залежності:
[]один раз, пропускається під час кожного відображення, перелік залежностей виводиться лише тоді, коли вони змінюються. - Час та мета очищення (витоки, скасування підписок/запитів).
- Чому ефекти виконуються двічі під час розробки — у суворому режимі React 18 виклики відбуваються двічі для виявлення пропущеного очищення. Майже кожен стикається з цим принаймні один раз.
useMemo vs useCallback
useMemoзберігає у кеші значення;useCallbackзберігає у кеші ідентичність функції.- Обидва забезпечують захист від різниці у посиланнях для дочірніх елементів
React.memoабо масивів залежностей. - Надмірне використання має наслідки; співрозмовники під час інтерв’ю люблять чути, що мемоізація не є безкоштовною.
useRef
- Змінна величина між відображеннями без перевідображення.
- Вузли DOM, попередні значення, ідентифікатори таймерів.
useContext
- Закінчує буріння пропсів для піддерева.
- Важливо: оновлення контексту переробляє кожного споживача в піддереві, включаючи тих, хто читає лише одне поле.
useReducer
- Краще використовувати, коли логіка складна або кілька полів оновлюються одночасно (локальні редьюсери у форматі Redux).
Custom hooks
- Будьте готові писати
useDebounce,useFetchабоuseLocalStorageна льоту — це один із найпоширеніших практичних завдань.
3. Відображення та продуктивність
На середньому/вищому рівнях тут відбувається сортування учасників.
- Чому відбувається переробка? через переробку батьківського елемента, зміну стану, зміну контексту або пропси, які виглядають однаково, але є новими посиланнями.
- React.memo — поверхневе порівняння пропсів; марне, якщо ви щоразу передаєте нові об’єкти/функції (використовуйте разом із
useMemo/useCallback).
React.lazy + Suspense.react-window для обробки величезних списків.Класична проблема: список з 10 000 рядків сповільнюється під час введення пошуку. Необхідно використовувати технології debounce, віртуалізацію та мемоування рядків.
4. Керування станом
- Локальний, глобальний та серверний стан — окреме позначення серверного стану (каша, перевірка даних, статус завантаження/помилки) від стану інтерфейсу справляє гарне враження на експертів.
- Context проти Redux/Zustand — Context для рідкісних глобальних параметрів (тема, автентифікація); Redux/Zustand у випадках, коли потрібні мідлвейри, інструменти, складні оновлення чи часте збереження даних без проблем із контекстом.
- React Query / SWR / TanStack Query — кешування, автоматичне оновлення у фоновому режимі, видалення дублікатів, щоб уникнути необхідності заново створювати механізми отримання даних за допомогою
useEffect. - Основи Redux (якщо стек використовує його): дії, редуктори, сховище даних, проміжні компоненти типу thunk/saga, чисті редуктори.
5. Шаблони проектування
- HOCs — обгортання компонента; класичний приклад —
withAuth. - Render props — спільне використання логіки через функційні параметри; переважно замінені гаками, але концепція все ще актуальна.
- Композитні компоненти — братські компоненти, які діляться неявним станом через контекст (
Select/Select.Option). - Контейнерні/презентаційні компоненти — розділення даних та користувацького інтерфейсу; з гаками це менш суворо регламентовано, але принцип розділення обов’язків залишається важливим.
- Композиція замість успадкування — основний підхід React до повторного використання коду; будьте готові його обґрунтувати.
6. Життєвий цикл класу (досі поширене питання)
Компанії, які використовують хуки на першому місці, все ще досліджують основи чи старі кодові бази.
componentDidMount≈useEffect(() => {}, [])componentDidUpdate≈ ефект із залежностямиcomponentWillUnmount≈ очищення ефектів- Межі помилок — лише для класів (
componentDidCatch/getDerivedStateFromError); у хуків немає аналога, тому існують обгортки на кшталтreact-error-boundary.
7. Обізнаність з React 18+
- Конкурентне відображення — можливість переривання роботи для більш швидкої відповіді інтерфейсу.
useTransition— позначення неекстрених оновлень, щоб введення тексту залишалося швидким.useDeferredValue— відкладає відображення некритичних елементів інтерфейсу.- Автоматичне групування — об’єднує операції всередині обіцянок, таймаутів та нативних обробників (не лише обробників React).
- Suspense для даних — особливо корисний у стеках у стилі Next.js/Remix.
- Server Components — що виконується де та чому зменшуються розміри клієнтських бандлів.
8. JavaScript, який таємно проникає
- Замикання — застарілий стан хуків.
- Цикл подій / мікро- та макрозавдання — чому групування відбувається саме так.
- Прив’язка
this— якщо використовуються класи. - Debounce vs throttle — майже завжди пропонується як спосіб «оптимізації цього поля пошуку».
- Порівняння поверхневе vs глибоке —
React.memo/useMemoта чому літерали об’єктів унеможливлюють мемоізацію. - Promises / async-await — конкуренція запитів під час швидкого введення користувачем.
9. Тестування
- Testing Library — орієнтація на поведінку, а не внутрішню реалізацію (запити до ролей/тексту).
- Jest — імітація API; необхідність дотримання обмежень щодо знімків стану.
- Юніт-тестування, інтеграційне та е2e-тестування, а також місце тестів компонентів.
10. Живе кодування з повторенням
- Затримане пошук/автодоповнення
- Скористатися власною функцією
useFetchз показником завантаження, помилок та даних - Безкінечне прокручування або сторінкування
- Модальне вікно через portal (
createPortal) та причина його існування (уникнення переповнення/зміни зоряного номера, водночас збереження у структурі React для обробки подій та контексту) - Лічильник із функціями скасування/повторення за допомогою
useReducer - Виявлення помилок через застарілі замикання або відсутні залежності
Приклад поетапного виконання
«Чому цей useEffect увійшов у нескінченний цикл?»
useEffect(() => {
setData({ ...data, updated: true });
}, [data]);
Чітка відповідь: ефект вказує data як залежність, а потім записує новий об’єкт назад у data, тож з кожним виконанням змінюється залежність та відразу ж відбувається повторне запускання. Щоб виправити це, потрібно вилучити data зі списку залежностей, коли це не потрібно, перенести оновлення поза межі ефекту або використати функціональний оновлювач із більш вузькими залежностями.
Пояснення чому це призводить до проблем — а не лише пропозиція виправлення — і є тим, що відрізняє якісні відповіді на інтерв’ю з React.
Закінчення
Глибина розуміння переважає над запам’ятовуванням лише поверхневих аспектів API. Інтерв’юери цікавляться поведінкою відображення контенту, концепцією замикань та компромісами у продуктивності — тими помилками, які з’являються у реальних умовах роботи. Готуйтесь, створюючи маленькі компоненти, які навмисно виявляють проблеми (старі замикання, відсутні залежності, марні повторні відображення), та виправляючи їх. Саме цей інстинкт відлову помилок є тим, що насправді оцінюється під час інтерв’ю.
Під час практики обмежуйте себе часом, як це робиться під час інтерв’ю: поясніть концепцію Virtual DOM протягом шістдесяти секунд, потім виправте проблему зі старим замиканням, а потім накресліть схему затриманого пошуку. Така послідовність відповідає тому, як насправді проходять інтерв’ю.
Як зазвичай ескалуються проблеми
Розігрівальні завдання стосуються Virtual DOM, керованих введень та клавіш. На середньому рівні розглядаються хуки: пакетні оновлення, проблема подвійних ефектів у Strict Mode, використання memo проти callback та створення власного хука на льоту. На вищому рівні йдеться про питання продуктивності — списки з десятьма тисячами рядків, проблеми з контекстом, дані з Profiler та вибір архітектури між Context, Redux/Zustand та TanStack Query для керування станом на сервері.
Тримайте особистий репозиторій з навмисно «пошкодженими» прикладами: лічильник з проблемою stale-closure, ефект відсутніх залежностей, мемоїзований список, який все одно перерендрується через вбудовані об’єкти, та модальне вікно типу portal. Опис цих чотирьох проблем вголос охоплює значну частину часу, приділеного прямому програмуванню та роботі на дошці.
Якщо у посадовій інструкції згадується React 18+, будьте готові навести по одному реченню про конкурентне відображення, переходи, відкладені значення, автоматичне пакетування та Server Components. Глибоке розуміння однієї конкретної ситуації краще, ніж поверхневе знання про всі RFC.