Собеседование frontend в 2026-м редко проваливается из-за «не назвал все CSS-свойства». Чаще ломается другое: человек знает React по курсу, но не может объяснить, почему список тормозит, куда девается состояние формы и что будет, если пользователь нажмёт «отправить» дважды. Нанимающий проверяет не энциклопедию фреймворка, а вероятность, что вы не сломаете кабинет на первом релизе.
Ниже — блоки, которые реально ставят на скрининге и техэкране, полные ответы, которые можно сказать вслух, и подготовка по вакансии, а не «по всему интернету». Общий каркас — вопросы на собеседовании. Самопрезентацию соберите отдельно, не внутри рассказа про замыкания. Смотреть, какой слот вам ближе, удобно по frontend-вакансиям.
Коротко:
- Готовьте глубоко стек из объявления: JS, CSS, один фреймворк. Не пять фреймворков «на всякий случай».
- Почти всегда спросят состояние, список, форму и что происходит при ошибке сети.
- Live coding проверяет ход мысли и простой рабочий путь, не идеальный архитектора.
- Один свой экран разберите до боли: данные, ререндер, доступность, что не сделали.
- Поведение и оценка объёма важны не меньше хуков: как вы режете скоуп и объясняете компромисс.
Как читать вакансию за 15 минут
Выпишите: фреймворк, TypeScript да/нет, кабинет или лендинги, дизайн-система, тесты, SSR/Next. Готовьте это. Если в вакансии React и формы, не тратьте неделю на Vue «вдруг спросят». Вторая проверка — объём: единственный фронт в стартапе и человек в команде с дизайн-системой — разные интервью.
Junior чаще ловят на HTML/CSS/JS и одном компоненте. Middle — на состоянии, производительности списка, доступности, работе с API. Senior — на границах: когда вынести в стейт-менеджер, как не убить бандл, как жить с легаси. Не готовьте senior-дизайн, если слот junior: вас услышат как человека не на ту роль.
Сверьтесь с тем, что уже лежит в frontend-резюме: если написали Next и GraphQL, будут копать. Если написали «адаптивная вёрстка» без факта — тоже спросят, и ответ развалится.
JavaScript: не определения, а сценарий
Спросят то, чем вы стреляете себе в ногу на практике: замыкание в цикле с обработчиком, this в колбэке, промис vs async, микротаски одной фразой, структурированное клонирование при postMessage — только если вакансия про это. Чаще: «что будет, если в обработчике await, а пользователь кликнул ещё раз».
Если обработчик async и нет защиты, второй клик запустит второй запрос, пока первый ещё в полёте. Я бы на кнопке сразу ставил disabled или флаг inFlight, а ответ первого запроса игнорировал бы, если уже ушли со экрана. Ошибку сети показываю рядом с формой, поля не сбрасываю: пользователь не должен набирать заново.
Про промисы на этом слоте мне важнее не «что такое event loop в учебнике», а порядок: сначала синхронно выставили состояние loading, потом fetch, потом setState по результату. Если setState после размонтирования — в новом React это уже не та боль, но я всё равно отменяю через AbortController, чтобы не долбить API зря.
Граница честно: тонкости очерёдности microtask/macrotask могу нарисовать на примере Promise.then и setTimeout, но на экране заказа я сначала закрываю двойной submit. Если копнёте в event loop — нарисую, не буду притворяться, что помню каждую спецификацию.
Почему это слышат как сильный ответ: есть пользовательский сценарий, есть отмена, есть граница знания. Нет лекции «замыкание это когда функция помнит лексическое окружение» без задачи.
CSS и вёрстка: кабинет, не лендинг с анимацией
В вакансиях на продукт спрашивают поток, флекс/грид, как не разъехать таблицу, как сделать фокус видимым, что будет на узком экране. Анимации и «сделайте как на Dribbble» — редкость, если вы не на маркетинг-сайт.
Типовой вопрос: «фильтры слева, таблица справа, на мобиле фильтры снизу. Как разложить?» Ответ — грид или флекс плюс что ломается при длинных данных, плюс overflow. Слабый ответ — «ну bootstrap». Сильный — где overflow, где sticky шапка таблицы, что с клавиатурой в фильтрах.
Десктоп: слева колонка фильтров фиксированной ширины, справа таблица с min-width и горизонтальным скроллом, если колонок много — не сжимаю цифры в кашу. Шапка таблицы sticky, чтобы при скролле строк не терять сортировку. Длинное название заказа — truncate с title, не ломаю высоту строки на три этажа без нужды. Мобил: фильтры уезжают в нижний лист или аккордеон, таблица становится карточками или тем же скроллом, не прячу обязательный столбец суммы.
Фокус: виден outline на фильтре и на строке, если строка кликабельна. Не вешаю click только на div. Если дизайнер принёс тень, которая перекрывает соседний контрол — это баг вёрстки, не «так в макете». Пустые данные: не прыгающий скелетон на 30 секунд, а явная пустая карточка и кнопка сброса фильтра.
React (или ваш фреймворк): состояние и список
Вопрос, который ставят постоянно: «список заказов, фильтр, детали справа. Где state?»
Фильтр и выбранный id — состояние экрана, не сервера. Список я бы держал как данные с сервера плюс статус loading/error, не как «массив, который сами мутируем в десяти местах». Детали — либо рядом, если уже пришли в списке, либо отдельный запрос по id, если в списке только шапка. Ключ в списке — стабильный id заказа, не индекс: иначе фильтр будет вспыхивать неправильными строками.
Лишний ререндер ловлю так: сначала смотрю, не поднял ли я слишком высоко состояние, из-за которого таблица перерисовывается на каждый символ в поиске. Поиск можно debounce, таблицу — мемоизировать строку, если профиль показал, что дорого. useMemo на всё подряд не ставлю: это шум, пока нет измерения.
Эффект с fetch кладу за зависимость от фильтра, не «в mount и забыли». Abort на смене фильтра, чтобы старый ответ не перетёр новый. Это тот баг, который я уже ловил в учебном кабинете: медленный запрос «все» прилетал после «оплаченные» и показывал не тот список.
Follow-up почти всегда: ключи, контролируемые инпуты, подъём состояния, контекст vs props. Готовьте одну фразу, зачем вам Redux/Zustand, если он в резюме: «много экранов делят корзину / черновик сложной формы». Если не делят — «не тащил бы».