Фронтенд-разработчик React (Профессиональный уровень)

Курс «Фронтенд-разработчик React (Профессиональный уровень)» предназначен для опытных разработчиков. Вы освоите продвинутые техники работы с React: управление состоянием (Redux Toolkit, Context API), TypeScript, асинхронные запросы (Axios, React Query), маршрутизацию (React Router), оптимизацию производительности и тестирование. На практике научитесь создавать масштабируемые SPA-приложения профессионального уровня.

Учебная программа курса «Фронтенд-разработчик React (Профессиональный уровень)» включает углубленное изучение библиотеки React и современных инструментов фронтенд-разработки. Курс состоит из следующих модулей:

 
  1. Продвинутый React — работа с хуками (useState, useEffect, useReducer, пользовательские хуки), управление контекстом через Context API, оптимизация рендеринга компонентов.
  2. Redux Toolkit — архитектура состояния, slice, thunk, работа с нормализованным состоянием.
  3. TypeScript в React — типизация компонентов, пропсов, событий, хуков, работа с generics и пересечениями типов.
  4. React Router v6+ — маршрутизация на продвинутом уровне, ленивая загрузка страниц, защита маршрутов, параметры URL.
  5. Работа с API — запросы через Axios и Fetch, обработка ошибок, кэширование данных с помощью React Query, SWR.
  6. Тестирование — написание unit- и интеграционных тестов с использованием Jest, React Testing Library, snapshot-тестирование.
  7. Оптимизация производительности — memoization, code splitting, серверный рендеринг (Next.js), работа с Webpack и Babel.
  8. Практика построения SPA — разработка масштабируемого приложения от проектирования архитектуры до деплоя.
 

Ожидаемые результаты после прохождения курса:

 

Должен уметь:

  • Разрабатывать высоконагруженные одностраничные приложения на React.
  • Применять TypeScript для обеспечения надежности кода.
  • Управлять состоянием приложений с Redux Toolkit и Context API.
  • Оптимизировать производительность React-приложений.
  • Реализовывать маршрутизацию, асинхронную работу с данными и обработку ошибок.
  • Писать автоматизированные тесты для компонентов и бизнес-логики.
  • Интегрироваться с REST/GraphQL API.
  • Строить архитектурно устойчивые приложения, соответствующие best practices.
 

Должен знать:

  • Принципы работы React-компонента и жизненного цикла.
  • Механизмы управления состоянием (Redux Toolkit, Context API).
  • Нюансы типизации в TypeScript применительно к React.
  • Современные подходы к маршрутизации, мемоизации и асинхронной обработке.
  • Подходы к структурированию проекта и разделению ответственности.
  • Основы SSR и SSG на примере Next.js.
  1. Что такое React и для чего он используется?
    React — это JavaScript-библиотека с открытым исходным кодом для создания пользовательских интерфейсов, особенно одностраничных приложений (SPA). Она позволяет разрабатывать интерактивные UI-компоненты декларативно, используя подход «один раз написал — можно использовать везде». React абстрагирует работу с DOM, упрощает обновление интерфейса при изменении состояния и предоставляет мощный механизм компонентной архитектуры.

  2. В чём разница между классовыми и функциональными компонентами в React?
    Классовые компоненты — это ES6-классы, расширяющие React.Componentподдерживают состояние через this.stateи жизненные циклыcomponentDidMountcomponentDidUpdateФункциональные компоненты — это обычные JS-функции, которые принимают props и возвращают JSX. С появлением хуков (например, useStateuseEffectфункциональные компоненты стали более популярными благодаря простоте и возможности управления состоянием без классов.

  3. Что такое JSX и как он работает в React?
    JSX (JavaScript XML) — это синтаксическое расширение JavaScript, позволяющее писать HTML-подобную разметку прямо в JavaScript-коде. При помощи Babel JSX преобразуется в вызовы React.createElement()Это делает создание UI более удобным и читаемым. Например: <div>Hello</div> превращается в React.createElement('div', null, 'Hello')

  4. Как управлять состоянием в React?
    Состояние (state) в React управляется с помощью хуков useStateuseReducerили классовых методовthis.statethis.setStateХуки предоставляют более простой способ работы со state в функциональных компонентах. Для сложных приложений рекомендуется использовать Redux Toolkit или Context API с useReducer

  5. Что такое props и как их использовать?
    Props (сокращение от properties) — это данные, передаваемые от родительского компонента к дочернему. Они неизменны внутри дочернего компонента. Props позволяют создавать переиспользуемые компоненты, например: <UserCard name="Alice" age={25} />

  6. Как работает useEffect в React?
    Хук useEffect позволяет выполнять побочные эффекты в функциональных компонентах. Он аналогичен componentDidMountcomponentDidUpdatecomponentWillUnmount в классовых компонентах. Пример: загрузка данных, подписка на события, мутации DOM. Второй аргумент — массив зависимостей, определяющий, когда запускать эффект.

  7. Что такое ключи (keys) в списке компонентов и зачем они нужны?
    Keys помогают React идентифицировать, какие элементы списка изменились, добавились или удалились. Это улучшает производительность рендеринга. Keys должны быть уникальными среди соседних элементов, но не обязательно глобально. Обычно используются ID из базы данных.

  8. Что такое контекст (Context API) и как его использовать?
    Context API позволяет передавать данные через дерево компонентов без необходимости явно передавать props на каждом уровне. Используется для передачи данных, доступных во всем приложении (например, тема, язык, авторизация). Создается с помощью React.createContext() и используется через Provider и useContext

  9. Что такое хуки (hooks) и какие ограничения у них есть?
    Хуки — это функции, которые позволяют использовать состояние и другие возможности React в функциональных компонентах. Ограничения: нельзя вызывать хуки внутри условий, циклов, вложенных функций; хуки можно вызывать только на верхнем уровне компонента или других хуков.

  10. Как тестировать React-компоненты?
    Для тестирования используются Jest и React Testing Library. Пишутся unit-тесты, интеграционные тесты, snapshot-тесты. Тестируются такие аспекты, как отображение, обработка событий, взаимодействие с API. Пример: проверить, что кнопка вызывает нужный обработчик при клике.

  11. Что такое React.memo и когда его использовать?
    React.memo — это HOC, который предотвращает повторный рендер компонента, если props не изменились. Полезен для оптимизации производительности. По умолчанию сравнивает props поверхностно, но можно передать свою функцию сравнения.

  12. Что такое useMemo и useCallback?
    useMemo возвращает мемоизированное значение, которое пересчитывается только при изменении зависимостей. useCallback возвращает мемоизированную функцию. Оба полезны для оптимизации, особенно при передаче колбэков в оптимизированные дочерние компоненты.

  13. Как работать с формами в React?
    Формы в React могут управляться через controlled components (состояние хранится в React), uncontrolled components (через ref), либо библиотеки вроде Formik, React Hook Form. Лучше использовать контролируемые компоненты для лучшей контроль над данными и валидацией.

  14. Что такое маршрутизация в React и как её реализовать?
    Маршрутизация реализуется через react-router-domПоддерживает SPA-навигацию без перезагрузки страницы. Используются компоненты BrowserRouterRouteLinkNavigateВ v6+ маршруты объявляются через объект или вложенную структуру.

  15. Что такое Redux и зачем он нужен?
    Redux — это шаблон управления состоянием приложения, основанный на принципах однонаправленного потока данных. Он централизует состояние приложения, обеспечивает предсказуемость изменений и упрощает отладку. Используется вместе с react-redux для интеграции с React.

  16. Что такое Redux Toolkit и чем он отличается от классического Redux?
    Redux Toolkit — официальная библиотека для упрощения работы с Redux. Упрощает создание хранилища, редьюсеров и экшенов. Автоматически иммутабельно мутирует состояние (через Immer), включает createSlicecreateAsyncThunkconfigureStoreРекомендуется для новых проектов вместо "чистого" Redux.

  17. Как отправлять HTTP-запросы в React?
    HTTP-запросы можно отправлять через fetchaxiosswrreact-queryAxios удобен из-за поддержки async/await, автоматической сериализации ответа и перехватчиков. React Query помогает кэшировать данные, управлять повторными запросами и фоновым обновлением.

  18. Что такое TypeScript и как он используется в React?
    TypeScript — это надмножество JavaScript с поддержкой типов. В React он позволяет строго типизировать props, состояние, события, хуки. Это улучшает читаемость кода, снижает количество ошибок и повышает качество автодополнения в IDE.

  19. Как организовать структуру проекта на React?
    Распространённые подходы: по функционалу features/entities/shared/по слоям components/containers/services/по модулямauth/profile/layout/Также часто используются шаблоны типа Feature-Sliced Design. Главное — соблюдать принцип разделения ответственности и переиспользования.

  20. Что такое SSR и SSG и как они реализуются в React?
    SSR (Server Side Rendering) — рендеринг на сервере, затем отправка готовой HTML-страницы клиенту. SSG (Static Site Generation) — генерация статических HTML-файлов на этапе сборки. Реализуются через Next.js, Gatsby. Улучшают SEO и время загрузки страницы.

  21. Как оптимизировать производительность React-приложения?
    Оптимизация включает: использование React.memouseMemouseCallbackленивую загрузкуReact.lazySuspensecode splitting, правильное управление состоянием, минимизацию rerender, профилирование через React DevTools Profiler.

  22. Как работать с изображениями и медиа в React?
    Изображения можно импортировать как модулиimport logo from './logo.png'или использовать URL-адреса. Для оптимизации используются next/imagegatsby-imageWebP-форматы, lazy loading, адаптивные изображения.

  23. Как деплоить React-приложение?
    Приложения можно деплоить через Vercel, Netlify, GitHub Pages, Firebase Hosting, AWS Amplify. Для этого используется npm run buildпосле чего файлы из build/ загружаются на хостинг. Настройка DNS, домена, CI/CD также важна.

  24. Как использовать CSS в React?
    CSS можно подключать глобально, использовать CSS-модули, styled-components, Emotion, Tailwind CSS. Каждый подход имеет свои преимущества: модульность, темизация, inline-стили, utility-first.

  25. Как организовать аутентификацию в React-приложении?
    Аутентификация может быть реализована через JWT, OAuth, Firebase Auth, Auth0. Данные пользователя хранятся в состоянии, localStorage, context или Redux. Защита маршрутов реализуется через HOC или useNavigate в React Router.

  1. Что такое порталы (Portals) в React и как их использовать?
    Порталы позволяют рендерить дочерние элементы вне иерархии DOM-компонента, но сохраняя контекст React. Используются для модальных окон, тултипсов, уведомлений. Реализуются через ReactDOM.createPortal(child, container)

  2. Как обрабатывать ошибки в React-компонентах?
    Для обработки ошибок используются Error Boundaries — классовые компоненты с методами static getDerivedStateFromError() или componentDidCatch()Они перехватывают ошибки в дочерних компонентах и могут отображать fallback UI вместо краха.

  3. Что такое асинхронные действия в Redux и как они работают?
    Асинхронные действия — это действия, которые выполняются не сразу, а после завершения асинхронной операции (например, HTTP-запроса). В Redux Toolkit используется createAsyncThunk для создания таких действий. Он автоматически генерирует типы экшеновpendingfulfilledrejectedи позволяет обрабатывать результат в редьюсере.

  4. Как реализовать ленивую загрузку (lazy loading) в React?
    Ленивая загрузка реализуется через React.lazy() и SuspenseНапример: const LazyComponent = React.lazy(() => import('./LazyComponent'))Компонент будет загружен только при первом рендере. Suspense отображает fallback во время загрузки.

  5. Что такое высокопроизводительные компоненты (Pure Components) в React?
    Pure Component — это классовый компонент, который автоматически реализует shouldComponentUpdate и сравнивает текущие props и state с предыдущими поверхностно. Это помогает избежать ненужных перерисовок. В функциональных компонентах аналог — React.memo

  6. Как работает механизм reconciliation в React?
    Reconciliation — это процесс сравнения нового виртуального DOM с предыдущим для определения минимального количества изменений в реальном DOM. React использует алгоритм diffing, основанный на предположении, что деревья сильно отличаются редко, поэтому он работает за O(n).

  7. Что такое фрагменты (Fragments) и зачем они нужны?
    Фрагменты позволяют группировать несколько элементов без добавления лишнего узла в DOM. Используются как <React.Fragment>...</React.Fragment> или короткая запись <>...</>Полезны, когда нужно вернуть несколько корневых элементов.

  8. Как передавать данные между несвязанными компонентами в React?
    Для передачи данных между несвязанными компонентами можно использовать Context API, Redux, Zustand, MobX или глобальный event bus. Лучше всего подходят Context + useReducer для средних приложений и Redux / Zustand для больших.

  9. Что такое HOC (Higher-Order Component) и как его создать?
    HOC — это функция, которая принимает компонент и возвращает новый компонент с дополнительными props или поведением. Пример: function withLogger(WrappedComponent) { return function(props) { console.log('Rendered'); return <WrappedComponent {...props} />; } }

  10. Как использовать пользовательские хуки (custom hooks)?
    Пользовательские хуки — это функции, начинающиеся с useкоторые могут вызывать другие хуки. Позволяют выносить логику состояния и эффектов в переиспользуемый код. Пример: useFetchuseLocalStorageuseFormValidation

  11. Как работать с localStorage в React?
    localStorage можно использовать через localStorage.getItem()localStorage.setItem()localStorage.removeItem()Для синхронизации с React-состоянием часто применяется useEffect и useState с начальным значением из localStorage.

  12. Что такое Webpack и как он используется в React-проектах?
    Webpack — это сборщик модулей, который объединяет JavaScript, CSS, изображения и другие ресурсы в один или несколько бандлов. В React-проектах он настраивается через webpack.config.js и управляет code splitting, lazy loading, loaders и plugins.

  13. Как использовать Babel в React-приложениях?
    Babel преобразует современный JavaScript (ES6+) в совместимый с более старыми браузерами. В React используется для преобразования JSX в React.createElement()-вызовы. Конфигурация осуществляется через .babelrc или babel.config.js

  14. Как организовать работу с переменными окружения в React?
    Переменные окружения задаются в файле .env, например REACT_APP_API_URL=http://api.example.comДоступ к ним осуществляется через process.env.REACT_APP_API_URLПеременные должны начинаться с REACT_APP_

  15. Что такое серверный рендеринг (SSR) и как он влияет на SEO?
    Серверный рендеринг (SSR) позволяет генерировать HTML-страницу на сервере, что улучшает индексацию поисковыми системами (SEO). В React SSR реализуется через Next.js, где страницы рендерятся на сервере с помощью getServerSideProps

  16. Как использовать TypeScript с Redux Toolkit?
    TypeScript обеспечивает строгую типизацию для состояния, экшенов и селекторов. При использовании createSlice можно указать тип состояния и тип payload. Также используется createSelector из reselect для мемоизации и типизации селекторов.

  17. Что такое микротаски и макротаски в JavaScript и как это связано с useEffect в React?
    Микротаски (Promise.then, MutationObserver) имеют приоритет над макротасками (setTimeout, setInterval, I/O). Хук useEffect выполняется после рендера, но до следующего цикла событий. Это важно для понимания порядка выполнения кода и side-effects.

  18. Как реализовать debounce и throttle в React с помощью хуков?
    Debounce и throttle можно реализовать с помощью useCallbacksetTimeout и useRefНапример, useDebounce(value, delay) возвращает значение с задержкой. Это полезно для поиска, скролла, изменения размера окна.

  19. Что такое suspense и как он используется в React?
    Suspense позволяет показывать fallback UI (например, спиннер) во время ожидания асинхронной операции, такой как ленивая загрузка компонента. Поддерживается через React.lazy()В будущем может поддерживать и другие асинхронные задачи.

  20. Как реализовать internationalization (i18n) в React-приложении?
    Для i18n используются библиотеки, такие как react-i18nextformatjslinguijsОни позволяют менять язык интерфейса динамически, форматировать даты, числа, валюты, а также загружать переводы по demand.

  21. Что такое strict mode в React и зачем он нужен?
    StrictMode — это инструмент для выявления потенциальных проблем в приложении. Он активирует дополнительные проверки и предупреждения в режиме разработки, такие как двойной запуск useEffect, использование устаревших методов.

  22. Как использовать ref в React и в чём разница между useRef и createRef?
    useRef возвращает изменяемый объект с .currentкоторый сохраняет своё значение между рендерами. createRef создаёт новый ref при каждом рендере. useRef предпочтителен в функциональных компонентах.

  23. Что такое Lifting State Up и когда его применять?
    Lifting State Up — это паттерн, при котором состояние поднимается в общего родителя, чтобы делиться им между несколькими дочерними компонентами. Применяется, когда несколько компонентов зависят от одного состояния или взаимодействуют друг с другом.

  24. Как обрабатывать события формы с useForm в React Hook Form?
    useForm из библиотеки react-hook-form предоставляет простой способ управления формами. Он регистрирует поля, валидирует значения, собирает данные и отправляет форму. Упрощает работу с контролируемыми и неконтролируемыми компонентами.

  25. Что такое code splitting и как он реализуется в React?
    Code splitting — это разделение кода на части для уменьшения размера начальной загрузки. Реализуется через React.lazy() и Suspenseлибо вручную через import() и Webpack-комментарии /* webpackChunkName: "my-chunk" */

  1. Как использовать Web Workers в React и зачем они нужны?
    Web Workers позволяют выполнять тяжелые вычисления в фоновом потоке, не блокируя основной поток. В React их можно использовать для обработки данных, шифрования, аналитики. Инициализируются через new Worker()обмен данными — через postMessage() и onmessage

  2. Что такое reselect и как он помогает в оптимизации Redux?
    Reselect — это библиотека для создания мемоизированных селекторов. Мемоизация позволяет избежать повторных вычислений, если входные данные не изменились. Это особенно полезно при работе с большими массивами или сложными преобразованиями данных.

  3. Как реализовать drag-and-drop в React без сторонних библиотек?
    Реализация drag-and-drop возможна через нативные события dragstartdragoverdropНеобходимо управлять состоянием перетаскиваемого элемента и его позиции. Для более сложных сценариев рекомендуется использовать библиотеки, например react-beautiful-dnd

  4. Что такое Virtual DOM и как он работает?
    Virtual DOM — это легковесное представление реального DOM. При изменении состояния React создает новый Virtual DOM, сравнивает его с предыдущей версией (diffing) и применяет минимальные изменения к реальному DOM для повышения производительности.

  5. Как работать с датами в React и какие библиотеки лучше использовать?
    Для работы с датами в React используются библиотеки date-fnsmoment.js (устаревшая), dayjsluxonОни предоставляют удобный API для форматирования, сравнения, вычисления разницы между датами и поддержки временных зон.

  6. Как организовать анимацию в React-приложениях?
    Анимации можно реализовать через CSS transitions/animations, библиотеки framer-motionreact-transition-groupGSAPFramer Motion предоставляет декларативный способ управления анимациями, включая вход/выход компонентов и жесты.

  7. Что такое Suspense SSR и как он влияет на рендеринг на сервере?
    Suspense SSR — это механизм, который позволяет приостанавливать рендеринг части дерева компонентов до выполнения асинхронного действия. Поддерживается в Next.js 13+ и используется вместе с use и React.lazy() для серверного рендера с ожиданием данных.

  8. Как использовать IndexedDB в React для локального хранения данных?
    IndexedDB — это клиентская база данных NoSQL, которая позволяет хранить значительные объемы структурированных данных. В React можно использовать обертки, такие как idbили работать напрямую через indexedDB.open()createObjectStoretransaction

  9. Что такое tree-shaking и как он работает в React?
    Tree-shaking — это процесс удаления неиспользуемого кода на этапе сборки. Он работает в Webpack, Rollup и Vite при использовании ES Modules. Позволяет значительно уменьшить размер финального бандла, исключая экспорты, которые не импортируются.

  10. Как реализовать работу с WebSocket в React?
    WebSocket поддерживает двустороннее соединение между клиентом и сервером. В React можно использовать нативный WebSocketлибо библиотеки вроде socket.io-clientСоединение обычно устанавливается в useEffectа сообщения обрабатываются через onmessage

  11. Что такое CSR и чем он отличается от SSR и SSG?
    CSR (Client Side Rendering) — рендеринг происходит на клиенте после загрузки JS. SSR (Server Side Rendering) — HTML генерируется на сервере, SSG (Static Site Generation) — HTML генерируется на этапе сборки. CSR быстрее для последующих переходов, SSR и SSG лучше для SEO и первоначальной загрузки.

  12. Как использовать Web Components в React?
    Web Components — это стандартные элементы, совместимые с любыми фреймворками. В React они используются как обычные HTML-элементы. Для передачи props и обработки событий используются refaddEventListenerdataset

  13. Что такое микросервисная архитектура и как она связана с React?
    Микросервисная архитектура предполагает разделение backend на небольшие автономные сервисы. В контексте React — это может быть микрофроненд: разделение UI на независимые части, каждая из которых развивается отдельно. Реализуется через Module Federation (Webpack 5).

  14. Как использовать WebAssembly в React-приложениях?
    WebAssembly позволяет запускать код, написанный на других языках (Rust, C++), в браузере. В React его можно использовать для вычислений высокой интенсивности. Подключается через fetch() и WebAssembly.instantiate() или через npm-пакеты, например wasm-bindgen

  15. Как реализовать темизацию (theming) в React-приложении?
    Темизация реализуется через Context API, ThemeProvider из styled-components / Emotion, либо CSS переменные. Состояние текущей темы хранится в контексте, а компоненты получают доступ к цветам, шрифтам и другим значениям по мере необходимости.

  16. Что такое Module Federation и как он используется в React?
    Module Federation — это функционал Webpack 5, позволяющий делиться модулями между приложениями. Используется для построения микрофронендов: один проект может динамически загружать и использовать компоненты из другого проекта без npm-зависимостей.

  17. Как реализовать offline-режим в React-приложении?
    Offline-режим достигается через Service Workers и Cache Storage. Используются библиотеки вроде Workbox для регистрации SW и кэширования ресурсов. Также возможно использование localStorage или IndexedDB для сохранения данных пользователя.

  18. Что такое headless CMS и как он интегрируется с React?
    Headless CMS — это система управления контентом без фронтенда. Данные предоставляются через API (REST или GraphQL). В React интеграция осуществляется через запросы к API CMS (например, Strapi, Contentful, Sanity) и отображение контента в компонентах.

  19. Как использовать GraphQL в React и какие библиотеки популярны?
    GraphQL в React используется через Apollo Client, Relay, RTK Query или urql. Эти библиотеки позволяют отправлять запросы, кэшировать результаты, управлять состоянием и подписываться на обновления через subscriptions.

  20. Что такое SWR и как он помогает в управлении данными?
    SWR (Stale-While-Revalidate) — это React Hooks библиотека для получения данных. Она автоматически кэширует ответы, повторно валидирует данные при фокусе на окне, повторяет запросы при ошибке и поддерживает мутации. Удобен для частых обновлений данных.

  21. Как реализовать пользовательскую систему плагинов в React?
    Плагины можно реализовать через динамический импорт import()контекст, публичные API, которые регистрируются в центральном хранилище. Каждый плагин предоставляет свой интерфейс, который может расширять функциональность приложения.

  22. Что такое barrel файлы и зачем они нужны?
    Barrel файлы — это index.js/ts файлы, которые собирают и экспортируют модули из нескольких файлов. Они упрощают импорт, скрывая внутреннюю структуру директории. Например: export * from './Button'

  23. Как использовать WebRTC в React для видеочата?
    WebRTC позволяет организовать прямое соединение между браузерами. В React можно использовать нативный RTCPeerConnectionлибо библиотеки вроде simple-peerОбмен ICE-кандидатами и SDP-описаниями происходит через сигнализационный сервер.

  24. Что такое feature flags и как их внедрить в React?
    Feature flags — это механизм условного включения/отключения функций. Реализуется через конфигурацию, переменные окружения, либо внешний сервис (например, LaunchDarkly). В React можно оборачивать компоненты в HOC или использовать контекст.

  25. Как реализовать CI/CD для React-проекта?
    CI/CD реализуется через GitHub Actions, GitLab CI, CircleCI, Jenkins. Pipeline включает: установку зависимостей, тестирование, сборкуnpm run buildдеплой на Vercel/Netlify/AWS. Также возможна проверка типов, линтинг, e2e-тесты.

  1. Какой хук используется для выполнения побочных эффектов в функциональных компонентах React?
    A) useEffect
    B) useState
    C) useReducer
    D) useContext
    Ответ: A

  2. Что возвращает метод ReactDOM.createPortal()?
    A) Новый экземпляр DOM-элемента
    B) Ссылку на корневой узел приложения
    C) JSX, отрендеренный в указанном DOM-узле
    D) Объект portal, который можно включать в JSX
    Ответ: D

  3. Какое значение по умолчанию возвращает createContext()?
    A) null
    B) undefined
    C) Пустой объект {}
    D) Значение не задано
    Ответ: B

  4. Что делает функция React.memo()?
    A) Оптимизирует рендеринг списка элементов
    B) Предотвращает повторный рендер компонента при изменении состояния
    C) Кэширует результат вычисления сложных функций
    D) Выполняет мемоизацию компонента по его props
    Ответ: D

  5. Какой тип ключа лучше всего использовать для элементов списка в React?
    A) Индекс элемента
    B) Уникальное строковое значение (например, UUID)
    C) Числовой идентификатор из БД
    D) Любое значение, главное — уникальность
    Ответ: B

  6. Что произойдет, если вызвать setState с тем же значением, что и текущее состояние?
    A) Компонент перерендерится
    B) React проигнорирует обновление
    C) Вызовет ошибку
    D) Перезагрузит страницу
    Ответ: B

  7. Как реализовать ленивую загрузку компонента в React?
    A) Использовать React.lazy() и Suspense
    B) Использовать import() внутри useEffect
    C) Применить асинхронный render в родительском компоненте
    D) Ленивая загрузка невозможна без Redux
    Ответ: A

  8. Что такое reconciliation в контексте React?
    A) Процесс сравнения DOM-дерева перед и после обновления
    B) Процесс создания нового Virtual DOM
    C) Процесс объединения стейта
    D) Процесс оптимизации props
    Ответ: A

  9. Как получить доступ к DOM-элементу в React?
    A) Через useRef()
    B) Через state
    C) Через props
    D) Через context
    Ответ: A

  10. Что возвращает хук useReducer()?
    A) Массив из текущего состояния и диспетчера
    B) Текущее состояние и функцию для его обновления
    C) Функцию dispatch и новое состояние
    D) Только текущее состояние
    Ответ: A

  11. Какие данные должны быть в состоянии (state), а не в переменной?
    A) Данные, которые никогда не изменяются
    B) Данные, влияющие на UI
    C) Данные, используемые только в одном компоненте
    D) Данные, полученные из API один раз
    Ответ: B

  12. Что такое Error Boundary в React?
    A) Компонент, который ловит ошибки рендера
    B) Встроенный обработчик исключений JavaScript
    C) Хук, отлавливающий ошибки
    D) Метод жизненного цикла классового компонента
    Ответ: A

  13. Какой тип данных нельзя передавать через Context в React?
    A) Объект
    B) Функция
    C) Примитив
    D) Все варианты допустимы
    Ответ: D

  14. Что происходит при вызове setState в componentWillUnmount()?
    A) Состояние обновляется, но компонент уже не отрендерен
    B) React выбросит ошибку
    C) Состояние не обновляется
    D) React предупредит о возможной утечке памяти
    Ответ: C

  15. Какой метод жизненного цикла вызывается сразу после монтирования компонента?
    A) componentWillMount()
    B) componentDidMount()
    C) render()
    D) shouldComponentUpdate()
    Ответ: B

  16. Что делает оператор spread в JSX?
    A) Передает пропсы как объект
    B) Распаковывает массив в элементы
    C) Вызывает функцию
    D) Ничего, он не работает в JSX
    Ответ: A

  17. Как проверить тип props в React?
    A) PropTypes
    B) TypeScript
    C) Flow
    D) Все вышеперечисленные
    Ответ: D

  18. Что возвращает React.Fragment?
    A) Обычный div
    B) Виртуальный узел без DOM-представления
    C) Корневой элемент
    D) Компонент, оборачивающий всё приложение
    Ответ: B

  19. Какой хук используется для получения ссылки на дочерний компонент?
    A) useRef()
    B) forwardRef()
    C) createRef()
    D) useImperativeHandle()
    Ответ: D

  20. Что делает React.PureComponent?
    A) Автоматически выполняет мемоизацию
    B) Реализует shouldComponentUpdate() поверхностного сравнения
    C) Не имеет методов жизненного цикла
    D) Оптимизирует работу с контекстом
    Ответ: B

  21. Какой тип обновления состояния гарантирует актуальное значение state?
    A) Передача нового значения напрямую
    B) Передача функции в setState
    C) Использование async/await
    D) Использование useEffect
    Ответ: B

  22. Что такое Portals в React?
    A) Механизм для работы с DOM вне дерева компонентов
    B) Рендеринг в iframe
    C) Специальная конструкция для условного рендера
    D) Подключение внешних библиотек
    Ответ: A

  23. Как обновить состояние на основе предыдущего значения с помощью useState()?
    A) Передать новое значение напрямую
    B) Передать функцию, принимающую prevValue
    C) Использовать useEffect
    D) Использовать useReducer
    Ответ: B

  24. Какой метод жизненного цикла позволяет предотвратить ненужный рендер?
    A) componentWillReceiveProps()
    B) shouldComponentUpdate()
    C) componentDidUpdate()
    D) UNSAFE_componentWillUpdate()
    Ответ: B

  25. Какой из следующих подходов считается лучшей практикой для обработки форм в React?
    A) Использовать uncontrolled components
    B) Использовать controlled components
    C) Использовать localStorage для хранения состояния формы
    D) Использовать Redux Form
    Ответ: B

  1. Какой хук используется для мемоизации функций в React?
    A) useMemo()
    B) useCallback()
    C) useEffect()
    D) useReducer()
    Ответ: B

  2. Что такое reconciliation algorithm в React и как он работает?
    A) Алгоритм сравнения DOM-деревьев на основе индексов и ключей
    B) Алгоритм управления состоянием приложения
    C) Механизм оптимизации рендера через PureComponent
    D) Система обработки событий в React
    Ответ: A

  3. Как правильно обновить вложенный объект в состоянии с помощью useState()?
    A) setObj({...obj, key: newValue})
    B) setObj(prev => ({...prev, key: newValue}))
    C) setObj({...obj.key, newValue})
    D) obj.key = newValue
    Ответ: B

  4. Что делает метод ReactDOM.render()?
    A) Создаёт новый Virtual DOM
    B) Обновляет существующий корневой узел
    C) Монтирует React-компонент в указанный DOM-узел
    D) Уничтожает текущее приложение
    Ответ: C

  5. Какой тип контекста лучше использовать для глобального состояния?
    A) Local state
    B) Redux store
    C) React Context API
    D) SessionStorage
    Ответ: C

  6. Что означает термин «lifting state up» в React?
    A) Перенос состояния из дочерних компонентов в родительский
    B) Хранение состояния в localStorage
    C) Передача состояния через props
    D) Использование useContext вместо Redux
    Ответ: A

  7. Как реализовать серверный рендеринг (SSR) в React-приложении?
    A) Через ReactDOM.renderToString()
    B) Через ReactDOM.createPortal()
    C) Через React.lazy()
    D) Через React.PureComponent
    Ответ: A

  8. Что происходит при вызове setState после unmount компонента?
    A) Состояние успешно обновляется
    B) Выбрасывается исключение
    C) Обновление игнорируется
    D) Происходит утечка памяти
    Ответ: D

  9. Какой хук используется для получения предыдущего значения пропсов или состояния?
    A) useRef()
    B) useState()
    C) useEffect()
    D) usePrevious() (пользовательский хук)
    Ответ: D

  10. Что такое controlled component в React?
    A) Компонент, который получает значение из state и обновляет его через handleChange
    B) Компонент, использующий defaultValue
    C) Компонент, управляющий формами через DOM
    D) Компонент, использующий localStorage для хранения данных
    Ответ: A

  11. Как получить доступ к props в статическом методе getDerivedStateFromProps()?
    A) Никак, props недоступны
    B) Из аргумента метода
    C) Из this.props
    D) Из контекста
    Ответ: B

  12. Что возвращает метод render() классового компонента?
    A) JSX
    B) JSX или null
    C) Текстовое значение
    D) Объект Virtual DOM
    Ответ: B

  13. Какое значение передается первым аргументом в reducer-функцию при использовании useReducer()?
    A) Текущее состояние
    B) Действие (action)
    C) Предыдущее состояние
    D) Новое состояние
    Ответ: A

  14. Что такое Higher-Order Component (HOC)?
    A) Функция, которая принимает компонент и возвращает новый компонент
    B) Классовый компонент с расширенным функционалом
    C) Компонент, принимающий children
    D) Функция, возвращающая JSX
    Ответ: A

  15. Какой тип обновления состояния не гарантирует актуальное значение props/state внутри эффекта?
    A) Асинхронные колбэки в useEffect
    B) Передача функции в setState
    C) Использование useReducer
    D) Прямая передача нового значения
    Ответ: A

  16. Что делает свойство key в списке элементов?
    A) Определяет порядок рендера
    B) Помогает React эффективно обновлять список
    C) Задаёт уникальное имя компонента
    D) Не влияет на производительность
    Ответ: B

  17. Как использовать Suspense для ленивой загрузки компонента?
    A) Обернуть React.lazy() в тег <Suspense>
    B) Вызвать import() внутри useEffect
    C) Использовать await внутри render
    D) Ленивая загрузка без Suspense невозможна
    Ответ: A

  18. Что делает хук useLayoutEffect()?
    A) Выполняет побочные эффекты до рендера
    B) Выполняет побочные эффекты после рендера, но до отрисовки браузера
    C) Выполняет эффект только один раз
    D) Аналогичен useEffect(), но запускается раньше
    Ответ: B

  19. Какой подход считается наиболее предпочтительным для работы с HTTP-запросами в React?
    A) useEffect() + fetch()
    B) componentDidMount() + XMLHttpRequest
    C) componentWillReceiveProps() + fetch
    D) Все варианты допустимы
    Ответ: A

  20. Что представляет собой Virtual DOM в React?
    A) Точную копию реального DOM
    B) Легковесное представление DOM для сравнения изменений
    C) Объект, создаваемый ReactDOM
    D) Встроенный механизм браузера
    Ответ: B

  21. Что происходит при повторном рендере компонента с одинаковым значением props?
    A) React всегда перерендеривает
    B) React может пропустить рендер при использовании React.memo()
    C) React генерирует ошибку
    D) React перезагружает страницу
    Ответ: B

  22. Какой хук позволяет сохранять значение между рендерами без вызова эффекта?
    A) useState()
    B) useRef()
    C) useMemo()
    D) useCallback()
    Ответ: B

  23. Что такое reconciliation key в React?
    A) Уникальный идентификатор элемента
    B) Специальный prop, помогающий React отличать элементы друг от друга
    C) Ключ контекста
    D) Индекс массива
    Ответ: B

  24. Какой из следующих способов рекомендуется использовать для оптимизации рендеринга списка?
    A) React.memo() для каждого элемента
    B) Использование индекса как key
    C) Использование useMemo() для всего списка
    D) PureComponent для родителя
    Ответ: A

  25. Что означает термин «reconciliation» в React?
    A) Сравнение Virtual DOM с реальным перед обновлением
    B) Сравнение props и state
    C) Сравнение контекстов
    D) Сравнение двух деревьев компонентов
    Ответ: A

  1. Какой хук используется для создания пользовательских хуков в React?
    A) useEffect()
    B) useState()
    C) useCustomHook()
    D) Нет специального хука, пользовательские хуки создаются как обычные функции
    Ответ: D

  2. Что такое reconciliation и как он влияет на производительность?
    A) Это процесс сравнения Virtual DOM перед обновлением — может улучшать производительность
    B) Это процесс монтирования компонентов — не влияет на производительность
    C) Это процесс обработки событий — ухудшает производительность
    D) Это процесс рендеринга JSX — не влияет на производительность
    Ответ: A

  3. Как правильно использовать асинхронные эффекты внутри useEffect()?
    A) Оборачивать в async/await напрямую
    B) Создавать асинхронную IIFE внутри useEffect()
    C) Использовать только синхронные эффекты
    D) Асинхронные эффекты запрещены в useEffect()
    Ответ: B

  4. Какое из следующих утверждений о PureComponent неверно?
    A) Реализует shouldComponentUpdate() с поверхностным сравнением props и state
    B) Рекомендуется использовать вместо Component для оптимизации
    C) Подходит для глубоких объектов без дополнительной логики
    D) Уменьшает количество ненужных перерисовок
    Ответ: C

  5. Что делает метод getSnapshotBeforeUpdate() в классовых компонентах?
    A) Возвращает значение, доступное в componentDidUpdate() до обновления DOM
    B) Возвращает значение после обновления DOM
    C) Выполняет побочный эффект до unmount
    D) Используется для работы с контекстом
    Ответ: A

  6. Как реализовать кастомный хук для получения размеров окна браузера?
    A) С использованием useEffect(), window.addEventListener и useState()
    B) Через componentDidMount() и window.resize
    C) Только через внешние библиотеки
    D) С помощью useRef() и window.onresize
    Ответ: A

  7. Что происходит при вызове setState в асинхронном колбэке вне зоны React?
    A) React не отслеживает изменения
    B) React автоматически триггерит перерисовку
    C) Происходит ошибка выполнения
    D) React предупреждает, но продолжает работу
    Ответ: A

  8. Какой тип данных лучше всего подходит для использования в качестве ключей (key) в списках?
    A) Индекс массива
    B) Случайная строка
    C) Уникальный идентификатор из БД
    D) Число, полученное из Date.now()
    Ответ: C

  9. Что представляет собой термин «controlled component» в React?
    A) Компонент, управляющий состоянием формы через DOM API
    B) Компонент, использующий defaultValue и innerHTML
    C) Компонент, который получает значение из state и управляет им через handleChange
    D) Компонент, использующий localStorage для хранения формы
    Ответ: C

  10. Как реализовать глобальное состояние в React без Redux?
    A) Использовать React Context API + useReducer
    B) Использовать только useState в корневом компоненте
    C) Хранить всё в localStorage
    D) Глобальное состояние невозможно создать без Redux
    Ответ: A

  11. Что возвращает хук useMemo()?
    A) Значение, вычисленное мемоизированным образом
    B) Функцию, которая будет вызвана позже
    C) Состояние, которое не изменяется
    D) Пропсы, прошедшие проверку
    Ответ: A

  12. Какое утверждение о работе Virtual DOM верно?
    A) React всегда полностью пересоздаёт DOM
    B) React работает напрямую с реальным DOM
    C) React сравнивает Virtual DOM с реальным и применяет минимальные изменения
    D) Virtual DOM заменяет собой реальный DOM
    Ответ: C

  13. Как получить доступ к ref дочернего элемента в функциональном компоненте?
    A) Использовать forwardRef и useImperativeHandle
    B) Передать ref через props
    C) Использовать createRef() внутри дочернего компонента
    D) Ref нельзя передавать
    Ответ: A

  14. Какой из следующих способов является наиболее эффективным для оптимизации рендера списка?
    A) Использование индекса как key
    B) Использование React.memo() для каждого элемента
    C) Использование PureComponent для родителя
    D) Все варианты одинаково эффективны
    Ответ: B

  15. Что произойдет, если передать в React.createContext() значение, которое затем изменится?
    A) Все потребители контекста получат новое значение
    B) Контекст не обновится без Provider
    C) Приложение перезапустится
    D) Изменения будут игнорироваться
    Ответ: B

  16. Какой из следующих подходов считается лучшей практикой для работы с формами в React?
    A) Uncontrolled components
    B) Controlled components
    C) Использование localStorage для хранения состояния
    D) Использование Redux Form
    Ответ: B

  17. Что делает Suspense в React?
    A) Откладывает рендеринг дочерних компонентов до загрузки асинхронного кода
    B) Отображает спиннер при ошибке
    C) Ускоряет рендеринг приложения
    D) Не влияет на поведение приложения
    Ответ: A

  18. Какой из следующих хуков позволяет сохранять ссылку на значение между рендерами, не вызывая повторного рендера?
    A) useState()
    B) useCallback()
    C) useRef()
    D) useMemo()
    Ответ: C

  19. Какой из следующих паттернов используется для разделения UI на независимые, повторно используемые части?
    A) HOC
    B) Render Props
    C) Component Composition
    D) Все вышеперечисленные
    Ответ: D

  20. Что такое reconciliation algorithm в React и как он влияет на производительность?
    A) Алгоритм, который минимизирует обновления DOM за счет сравнения Virtual DOM
    B) Алгоритм, который увеличивает нагрузку на браузер
    C) Алгоритм, который не влияет на производительность
    D) Алгоритм, который перерисовывает весь DOM при каждом изменении
    Ответ: A

  21. Какой из следующих подходов позволяет уменьшить количество повторных рендеров компонентов?
    A) React.memo()
    B) useEffect()
    C) useContext()
    D) useLayoutEffect()
    Ответ: A

  22. Что возвращает ReactDOM.hydrate()?
    A) Тот же результат, что и ReactDOM.render(), но для SSR
    B) Рендеринг на сервере
    C) Отрисовка HTML-страницы
    D) Очистка DOM
    Ответ: A

  23. Какой из следующих хуков следует использовать для выполнения эффектов, зависящих от layout?
    A) useEffect()
    B) useLayoutEffect()
    C) useMemo()
    D) useCallback()
    Ответ: B

  24. Что происходит при использовании useEffect() без зависимостей?
    A) Эффект выполняется при каждом рендере
    B) Эффект выполняется только при монтировании
    C) Эффект не выполняется никогда
    D) Эффект выполняется при размонтировании
    Ответ: A

  25. Какое утверждение о работе React.StrictMode неверно?
    A) Он активирует дополнительные проверки и предупреждения
    B) Он вызывает двойной рендер в режиме разработки
    C) Он влияет на поведение приложения в продакшене
    D) Он помогает находить потенциальные проблемы
    Ответ: C

Экзаменационный билет №1

Теоретическая часть

  1. Объясните, в чём заключается разница между useEffect и useLayoutEffectПриведите примеры ситуаций, когда следует использовать каждый из них.

  2. Что такое reconciliation в React и как он влияет на производительность рендеринга? Опишите принцип работы алгоритма согласования.

 

Ответы на теоретическую часть:

  1. useEffect запускается асинхронно после завершения рендера и отрисовки компонента в браузере — это стандартное поведение для большинства побочных эффектов (например, подписки, API-запросы).
    useLayoutEffect запускается синхронно сразу после рендера, но до того, как браузер перерисует экран — используется, если нужно прочитать макет или размеры DOM перед отображением (например, позиционирование попапа).
  2. Reconciliation — это процесс сравнения нового Virtual DOM с предыдущим, чтобы определить минимальные изменения для обновления реального DOM. Это позволяет React работать эффективно, минимизируя дорогостоящие операции. Алгоритм использует стратегию сравнения по типу элементов и ключамkeyчто особенно важно при работе со списками.
 

Практическая часть

Реализуйте пользовательский хук useLocalStorageкоторый принимает ключ и начальное значение, и возвращает массив [value, setValue, clearValue]Значение должно сохраняться в localStorage и восстанавливаться при повторном монтировании. Также реализуйте функцию clearValueкоторая удаляет запись из localStorageи сбрасывает значение к начальному.

const useLocalStorage = (key, initialValue) => {
  const [value, setValue] = useState(() => {
    try {
      const storedValue = localStorage.getItem(key);
      return storedValue !== null ? JSON.parse(storedValue) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  const clearValue = () => {
    localStorage.removeItem(key);
    setValue(initialValue);
  };

  return [value, setValue, clearValue];
};

 

Экзаменационный билет №2

Теоретическая часть

  1. Что такое «controlled components» и зачем они используются в React? Объясните, почему их предпочтительно использовать вместо uncontrolled компонентов.

  2. Охарактеризуйте механизм работы React.memo() и useMemo()В чём разница между ними и в каких случаях следует использовать каждый из них?

 

Ответы на теоретическую часть:

  1. Controlled components — это элементы формы например, <input><select>состояние которых управляется через state в React-компоненте. Это позволяет централизованно контролировать данные, обрабатывать изменения и валидацию, а также синхронизировать состояние формы с другими частями приложения. Такой подход обеспечивает однонаправленный поток данных и делает форму более предсказуемой и управляемой по сравнению с uncontrolled компонентами, которые полагаются на DOM для хранения состояния.
  2. React.memo() — это Higher-Order Component, используемый для оптимизации рендеринга дочерних компонентов. Он предотвращает повторный рендер компонента, если его props не изменились. Применяется для компонентов, которые часто получают одни и те же props и дорогостоящие перерисовки.
 

Практическая часть

Реализуйте компонент AutoSuggestInputпринимающий список строкoptionsи функцию onSelectКомпонент должен отображать текстовое поле и выпадающий список совпадений по мере ввода. При выборе варианта из списка вызывается onSelectа введённое значение должно обновляться. Поиск должен быть регистронезависимым. Добавьте возможность фильтрации только тех вариантов, которые содержат введённую подстроку.

const AutoSuggestInput = ({ options, onSelect }) => {
  const [query, setQuery] = useState('');
  const [isOpen, setIsOpen] = useState(false);

  const filteredOptions = useMemo(() => {
    if (!query) return options;
    const lowerQuery = query.toLowerCase();
    return options.filter(option =>
      option.toLowerCase().includes(lowerQuery)
    );
  }, [options, query]);

  const handleSelect = (option) => {
    setQuery(option);
    setIsOpen(false);
    onSelect(option);
  };

  return (
    <div style={{ position: 'relative' }}>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        onFocus={() => setIsOpen(true)}
        placeholder="Введите запрос"
      />
      {isOpen && filteredOptions.length > 0 && (
        <ul style={{
          position: 'absolute',
          top: '100%',
          left: 0,
          right: 0,
          maxHeight: '200px',
          overflowY: 'auto',
          border: '1px solid #ccc',
          backgroundColor: '#fff',
          zIndex: 1000,
          listStyle: 'none',
          margin: 0,
          padding: 0
        }}>
          {filteredOptions.map((option, index) => (
            <li
              key={index}
              onClick={() => handleSelect(option)}
              style={{ padding: '8px', cursor: 'pointer' }}
              onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#f0f0f0'}
              onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
            >
              {option}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

 

Экзаменационный билет №3

Теоретическая часть

  1. Объясните, что такое Virtual DOM и как он помогает в повышении производительности React-приложений.

  2. Что такое Higher-Order Component (HOC)? Приведите пример использования и укажите его основные преимущества и недостатки.

 

Ответы на теоретическую часть:

  1. Virtual DOM — это легковесное представление реального DOM, используемое React для эффективного обновления интерфейса. При изменении состояния React создаёт новый Virtual DOM, сравнивает его со старым (reconciliation), вычисляет минимальные изменения и применяет их к реальному DOM. Это позволяет избежать частых и дорогостоящих операций обновления DOM напрямую, тем самым повышая производительность приложения.
  2. Higher-Order Component (HOC) — это функция, которая принимает компонент и возвращает новый компонент с дополнительным поведением или props. Используется для повторного использования логики между компонентами (например, авторизация, загрузка данных).
 

Практическая часть

Реализуйте пользовательский хук useDebounceкоторый принимает значение и задержку, и возвращает это значение с задержкой обновления. Хук должен быть полезен при реализации поиска с debounce, чтобы не отправлять запросы слишком часто.

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

 

Экзаменационный билет №4

Теоретическая часть

  1. Что такое «uncontrolled components» в React? В каких случаях их использование оправдано и какие инструменты предоставляет React для работы с ними?

  2. Объясните, что такое Portals в React и приведите примеры использования.

 

Ответы на теоретическую часть:

  1. Uncontrolled components — это элементы формы например, <input><textarea><select> состояние которых управляется напрямую DOM-элементом, а не React. Для доступа к их значению используется refТакие компоненты полезны при простых формах или интеграции с не-React библиотеками, где нет необходимости синхронизировать состояние в React.
  2. Portals в React позволяют рендерить дочерние элементы вне иерархии родительского компонента в произвольном DOM-узле. Это особенно полезно для модальных окон, тултипов, уведомлений и других UI-компонентов, которые должны отображаться поверх основного контента без влияния на структуру CSS-позиционирования.
 

Практическая часть

Реализуйте функциональный компонент ModalWindowкоторый принимает children и onCloseМодальное окно должно появляться при нажатии на кнопку "Открыть", затем отображать содержимое и закрываться по клику на фон или кнопку "Закрыть". Используйте портал для вывода окна в корневой элемент #modal-root

const ModalWindow = ({ children, onClose }) => {
  const modalRoot = document.getElementById('modal-root');

  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handleEscape);
    return () => window.removeEventListener('keydown', handleEscape);
  }, [onClose]);

  const handleOverlayClick = (e) => {
    if (e.target === e.currentTarget) onClose();
  };

  const modalContent = (
    <div className="modal-overlay" onClick={handleOverlayClick}>
      <div className="modal-content">
        <button className="close-button" onClick={onClose}>×</button>
        {children}
      </div>
    </div>
  );

  return ReactDOM.createPortal(modalContent, modalRoot);
};

// Пример использования:

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsModalOpen(true)}>Открыть модальное окно</button>

      {isModalOpen && (
        <ModalWindow onClose={() => setIsModalOpen(false)}>
          <h2>Модальное окно</h2>
          <p>Это содержимое модального окна.</p>
        </ModalWindow>
      )}
    </div>
  );
}

 

Экзаменационный билет №5

Теоретическая часть

  1. Что такое React Context API и в каких случаях она применяется? Какие основные компоненты предоставляет Context API?

  2. Охарактеризуйте работу хука useReducerВ чём его преимущество перед useState и когда он наиболее уместен?

 

Ответы на теоретическую часть:

  1. React Context API — это механизм передачи данных через дерево компонентов без необходимости явно передавать props на каждом уровне. Чаще всего используется для передачи глобального состояния, такого как тема приложения, данные авторизации, языковые настройки и т. д.
  2. Хук useReducerиспользуется для управления сложным состоянием, особенно если оно содержит несколько подзначений или если следующее состояние зависит от предыдущего. Он похож на Redux: принимает редюсер (функцию, которая возвращает новое состояние на основе действия) и начальное состояние.
 

Практическая часть

Реализуйте простую форму входа с помощью useReducerгде состояние включает emailpasswordisLoadingerrorДобавьте валидацию email и возможность отправки формы. Форма должна иметь кнопку "Войти" и отображать ошибку, если ввод некорректный или запрос не удался.

const formReducer = (state, action) => {
  switch (action.type) {
    case 'change_email':
      return { ...state, email: action.payload, error: '' };
    case 'change_password':
      return { ...state, password: action.payload, error: '' };
    case 'submit_start':
      return { ...state, isLoading: true, error: '' };
    case 'submit_success':
      return { ...state, isLoading: false };
    case 'submit_error':
      return { ...state, isLoading: false, error: action.payload };
    case 'validate_email':
      return { ...state, error: 'Введите корректный email' };
    default:
      return state;
  }
};

const LoginForm = () => {
  const [state, dispatch] = useReducer(formReducer, {
    email: '',
    password: '',
    isLoading: false,
    error: ''
  });

  const handleSubmit = (e) => {
    e.preventDefault();

    const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.email);
    if (!isValidEmail) {
      dispatch({ type: 'validate_email' });
      return;
    }

    dispatch({ type: 'submit_start' });

    // Мокаем асинхронный запрос
    setTimeout(() => {
      if (state.password.length < 6) {
        dispatch({ type: 'submit_error', payload: 'Неверный пароль' });
      } else {
        dispatch({ type: 'submit_success' });
        alert('Вход выполнен успешно');
      }
    }, 1000);
  };

  return (
    <form onSubmit={handleSubmit} style={{ maxWidth: '300px', margin: 'auto' }}>
      <h2>Вход</h2>
      {state.error && <div style={{ color: 'red' }}>{state.error}</div>}
      <div>
        <label>Email:</label>
        <input
          type="text"
          value={state.email}
          onChange={(e) => dispatch({ type: 'change_email', payload: e.target.value })}
        />
      </div>
      <div>
        <label>Пароль:</label>
        <input
          type="password"
          value={state.password}
          onChange={(e) => dispatch({ type: 'change_password', payload: e.target.value })}
        />
      </div>
      <button type="submit" disabled={state.isLoading}>
        {state.isLoading ? 'Загрузка...' : 'Войти'}
      </button>
    </form>
  );
};

 

Экзаменационный билет №6

Теоретическая часть

  1. Охарактеризуйте, как работает механизм reconciliation в React и какие стратегии используются для повышения его эффективности.

  2. Что такое пользовательские хуки (custom hooks) и какие правила их создания и использования в React?

Ответы на теоретическую часть:

  1. Reconciliation — это процесс сравнения нового Virtual DOM с предыдущим, чтобы определить минимальные изменения для обновления реального DOM. Это позволяет React работать максимально производительно, избегая полной перерисовки интерфейса.
  2. Пользовательские хуки — это функции, начинающиеся с префикса useкоторые могут использовать встроенные хуки ReactuseStateuseEffectuseContextи др. для реализации повторно используемой логики между компонентами. Они не создают собственного контекста рендера, а просто абстрагируют состояние и побочные эффекты.
 

Практическая часть

Реализуйте пользовательский хук useFetchкоторый принимает URL и параметры запроса, и возвращает объект { data, loading, error }Хук должен выполнять fetch-запрос, обрабатывать ошибки и поддерживать отмену запроса при размонтировании компонента.

const useFetch = (url, options = {}) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;
    const abortController = new AbortController();

    const fetchData = async () => {
      try {
        const response = await fetch(url, {
          ...options,
          signal: abortController.signal
        });

        if (!response.ok) throw new Error(`Ошибка HTTP: ${response.status}`);

        const result = await response.json();

        if (isMounted) {
          setData(result);
          setLoading(false);
        }
      } catch (err) {
        if (isMounted && err.name !== 'AbortError') {
          setError(err.message);
          setLoading(false);
        }
      }
    };

    fetchData();

    return () => {
      isMounted = false;
      abortController.abort();
    };
  }, [url, options]);

  return { data, loading, error };
};

 

Экзаменационный билет №7

Теоретическая часть

  1. Объясните, что такое PureComponent и React.memo. В чём их отличие и когда следует использовать каждый из них?

  2. Что такое порталы в React и зачем они нужны? Приведите примеры использования.

 

Ответы на теоретическую часть:

 

  1. PureComponent — это базовый класс для классовых компонентов, реализующий метод shouldComponentUpdate() с поверхностным сравнением props и state. Он предотвращает ненужный рендер, если данные не изменились.

    React.memo — это Higher-Order Component, который применяется к функциональным компонентам и делает то же самое — сравнивает props и пропускает рендер, если они не изменились.

    Разница:

    • PureComponent работает с классовыми компонентами.
    • React.memo — с функциональными.
    • React.memo можно расширить, передав свою функцию сравнения вторым аргументом.
     

    Используется, когда нужно оптимизировать рендеринг часто используемых компонентов, особенно в списках или табличных данных.

  2. Portals в React позволяют рендерить дочерние элементы вне иерархии родительского компонента в произвольном DOM-узле. Это особенно полезно для модальных окон, уведомлений, тултипов и других UI-компонентов, которые должны быть позиционированы вне текущего контекста CSS.
 

Практическая часть

Создайте компонент TabPanelпринимающий массив вкладок tabsи отображающий содержимое активной вкладки. Каждая вкладка должна иметь заголовок и содержимое. При клике на вкладку должно меняться состояние активной вкладки. Добавьте возможность отключения вкладок и стилизовать активную вкладку.

const TabPanel = ({ tabs }) => {
  const [activeIndex, setActiveIndex] = useState(0);

  const handleTabClick = (index) => {
    if (!tabs[index].disabled) {
      setActiveIndex(index);
    }
  };

  return (
    <div className="tab-panel">
      <div className="tab-list" role="tablist">
        {tabs.map((tab, index) => (
          <button
            key={index}
            role="tab"
            aria-selected={index === activeIndex}
            disabled={tab.disabled}
            onClick={() => handleTabClick(index)}
            className={`tab-button ${index === activeIndex ? 'active' : ''}`}
          >
            {tab.title}
          </button>
        ))}
      </div>
      <div className="tab-content" role="tabpanel">
        {tabs[activeIndex].content}
      </div>
    </div>
  );
};

// Пример использования:
function App() {
  const tabs = [
    {
      title: 'Вкладка 1',
      content: <p>Содержимое первой вкладки.</p>,
      disabled: false
    },
    {
      title: 'Вкладка 2',
      content: <p>Содержимое второй вкладки.</p>,
      disabled: false
    },
    {
      title: 'Заблокировано',
      content: <p>Эта вкладка отключена.</p>,
      disabled: true
    }
  ];

  return <TabPanel tabs={tabs} />;
}

 

Экзаменационный билет №8

Теоретическая часть

  1. Объясните, в чём заключается разница между useEffect и useLayoutEffectПриведите примеры ситуаций, когда следует использовать каждый из них.

  2. Что такое «controlled components» и зачем они используются в React? Объясните, почему их предпочтительно использовать вместо uncontrolled компонентов.

 

Ответы на теоретическую часть:

 

  1. useEffect запускается асинхронно после завершения рендера и отрисовки компонента в браузере — это стандартное поведение для большинства побочных эффектов (например, подписки, API-запросы).

    useLayoutEffect запускается синхронно сразу после рендера, но до того, как браузер перерисует экран — используется, если нужно прочитать макет или размеры DOM перед отображением (например, позиционирование попапа, обновление стилей динамически).

    Используйте useLayoutEffectесли вам нужно выполнить изменения, которые влияют на визуальное представление элемента до его отрисовки.

  2. Controlled components — это элементы формы например, <input><select>состояние которых управляется через stateв React-компоненте. Это позволяет централизованно контролировать данные, обрабатывать изменения и валидацию, а также синхронизировать состояние формы с другими частями приложения.
 

Практическая часть

Реализуйте пользовательский хук useDebounceкоторый принимает значение и задержку, и возвращает это значение с задержкой обновления. Хук должен быть полезен при реализации поиска с debounce, чтобы не отправлять запросы слишком часто.

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

 

Экзаменационный билет №9

Теоретическая часть

  1. Что такое Virtual DOM и как он помогает в повышении производительности React-приложений?

  2. Что такое Higher-Order Component (HOC)? Приведите пример использования и укажите его основные преимущества и недостатки.

 

Ответы на теоретическую часть:

  1. Virtual DOM — это легковесное представление реального DOM, используемое React для эффективного обновления интерфейса. При изменении состояния React создаёт новый Virtual DOM, сравнивает его со старым (reconciliation), вычисляет минимальные изменения и применяет их к реальному DOM. Это позволяет избежать частых и дорогостоящих операций обновления DOM напрямую, тем самым повышая производительность приложения.
  2. Higher-Order Component (HOC) — это функция, которая принимает компонент и возвращает новый компонент с дополнительным поведением или props. Используется для повторного использования логики между компонентами (например, авторизация, загрузка данных).
 

Практическая часть

Реализуйте компонент AutoSuggestInputпринимающий список строкoptionsи функцию onSelectКомпонент должен отображать текстовое поле и выпадающий список совпадений по мере ввода. При выборе варианта из списка вызывается onSelectа введённое значение должно обновляться. Поиск должен быть регистронезависимым. Добавьте возможность фильтрации только тех вариантов, которые содержат введённую подстроку.

const AutoSuggestInput = ({ options, onSelect }) => {
  const [query, setQuery] = useState('');
  const [isOpen, setIsOpen] = useState(false);

  const filteredOptions = useMemo(() => {
    if (!query) return options;
    const lowerQuery = query.toLowerCase();
    return options.filter(option =>
      option.toLowerCase().includes(lowerQuery)
    );
  }, [options, query]);

  const handleSelect = (option) => {
    setQuery(option);
    setIsOpen(false);
    onSelect(option);
  };

  return (
    <div style={{ position: 'relative' }}>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        onFocus={() => setIsOpen(true)}
        placeholder="Введите запрос"
      />
      {isOpen && filteredOptions.length > 0 && (
        <ul style={{
          position: 'absolute',
          top: '100%',
          left: 0,
          right: 0,
          maxHeight: '200px',
          overflowY: 'auto',
          border: '1px solid #ccc',
          backgroundColor: '#fff',
          zIndex: 1000,
          listStyle: 'none',
          margin: 0,
          padding: 0
        }}>
          {filteredOptions.map((option, index) => (
            <li
              key={index}
              onClick={() => handleSelect(option)}
              style={{ padding: '8px', cursor: 'pointer' }}
              onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#f0f0f0'}
              onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
            >
              {option}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

 

Экзаменационный билет №10

Теоретическая часть

  1. Что такое reconciliation и как он влияет на производительность рендеринга? Опишите принцип работы алгоритма согласования.

  2. Что такое React Context API и в каких случаях она применяется? Какие основные компоненты предоставляет Context API?

 

Ответы на теоретическую часть:

 

  1. Reconciliation — это процесс сравнения нового Virtual DOM с предыдущим, чтобы определить минимальные изменения для обновления реального DOM. Это позволяет React работать максимально производительно, избегая полной перерисовки интерфейса. Алгоритм использует два ключевых подхода:
    • Сравнение по типу элемента: если типы элементов разные — узел полностью заменяется.
    • Использование key для корректного сравнения элементов списка, что помогает React точно определить, какие элементы были изменены, добавлены или удалены.
  2. React Context API — это механизм передачи данных через дерево компонентов без необходимости явно передавать props на каждом уровне. Чаще всего используется для передачи глобального состояния, такого как тема приложения, данные авторизации, языковые настройки и т. д.

Практическая часть

Реализуйте пользовательский хук useLocalStorageкоторый принимает ключ и начальное значение, и возвращает массив [value, setValue, clearValue]Значение должно сохраняться в localStorage и восстанавливаться при повторном монтировании. Также реализуйте функцию clearValueкоторая удаляет запись из localStorageи сбрасывает значение к начальному.

const useLocalStorage = (key, initialValue) => {
  const [value, setValue] = useState(() => {
    try {
      const storedValue = localStorage.getItem(key);
      return storedValue !== null ? JSON.parse(storedValue) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  const clearValue = () => {
    localStorage.removeItem(key);
    setValue(initialValue);
  };

  return [value, setValue, clearValue];
};

 

Экзаменационный билет №11

Теоретическая часть

  1. Что такое «uncontrolled components» в React? В каких случаях их использование оправдано и какие инструменты предоставляет React для работы с ними?

  2. Объясните, что такое Portals в React и приведите примеры использования.

 

Ответы на теоретическую часть:

  1. Uncontrolled components — это элементы формы например, <input><textarea><select>состояние которых управляется напрямую DOM-элементом, а не React. Для доступа к их значению используется refТакие компоненты полезны при простых формах или интеграции с не-React библиотеками, где нет необходимости синхронизировать состояние в React.
  2. Portals в React позволяют рендерить дочерние элементы вне иерархии родительского компонента в произвольном DOM-узле. Это особенно полезно для модальных окон, тултипов, уведомлений и других UI-компонентов, которые должны отображаться поверх основного контента без влияния на структуру CSS-позиционирования.
 

Практическая часть

Реализуйте функциональный компонент ModalWindowкоторый принимает children и onCloseМодальное окно должно появляться при нажатии на кнопку "Открыть", затем отображать содержимое и закрываться по клику на фон или кнопку "Закрыть". Используйте портал для вывода окна в корневой элемент #modal-root

const ModalWindow = ({ children, onClose }) => {
  const modalRoot = document.getElementById('modal-root');

  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handleEscape);
    return () => window.removeEventListener('keydown', handleEscape);
  }, [onClose]);

  const handleOverlayClick = (e) => {
    if (e.target === e.currentTarget) onClose();
  };

  const modalContent = (
    <div className="modal-overlay" onClick={handleOverlayClick}>
      <div className="modal-content">
        <button className="close-button" onClick={onClose}>×</button>
        {children}
      </div>
    </div>
  );

  return ReactDOM.createPortal(modalContent, modalRoot);
};

// Пример использования:

function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsModalOpen(true)}>Открыть модальное окно</button>

      {isModalOpen && (
        <ModalWindow onClose={() => setIsModalOpen(false)}>
          <h2>Модальное окно</h2>
          <p>Это содержимое модального окна.</p>
        </ModalWindow>
      )}
    </div>
  );
}

 

Экзаменационный билет №12

Теоретическая часть

  1. Охарактеризуйте работу хука useReducerВ чём его преимущество перед useState и когда он наиболее уместен?

  2. Что такое reconciliation в React и как он влияет на производительность рендеринга? Опишите принцип работы алгоритма согласования.

Ответы на теоретическую часть:

  1. Хук useReducer используется для управления сложным состоянием, особенно если оно содержит несколько подзначений или если следующее состояние зависит от предыдущего. Он похож на Redux: принимает редюсер (функцию, которая возвращает новое состояние на основе действия) и начальное состояние.
  2. Reconciliation — это процесс сравнения нового Virtual DOM с предыдущим, чтобы определить минимальные изменения для обновления реального DOM. Это позволяет React работать максимально производительно, избегая полной перерисовки интерфейса. Алгоритм использует два ключевых подхода:
    • Сравнение по типу элемента: если типы элементов разные — узел полностью заменяется.
    • Использование key для корректного сравнения элементов списка, что помогает React точно определить, какие элементы были изменены, добавлены или удалены.
 

Практическая часть

Реализуйте простую форму входа с помощью useReducerгде состояние включает emailpasswordisLoadingerrorДобавьте валидацию email и возможность отправки формы. Форма должна иметь кнопку "Войти" и отображать ошибку, если ввод некорректный или запрос не удался.

const formReducer = (state, action) => {
  switch (action.type) {
    case 'change_email':
      return { ...state, email: action.payload, error: '' };
    case 'change_password':
      return { ...state, password: action.payload, error: '' };
    case 'submit_start':
      return { ...state, isLoading: true, error: '' };
    case 'submit_success':
      return { ...state, isLoading: false };
    case 'submit_error':
      return { ...state, isLoading: false, error: action.payload };
    case 'validate_email':
      return { ...state, error: 'Введите корректный email' };
    default:
      return state;
  }
};

const LoginForm = () => {
  const [state, dispatch] = useReducer(formReducer, {
    email: '',
    password: '',
    isLoading: false,
    error: ''
  });

  const handleSubmit = (e) => {
    e.preventDefault();

    const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.email);
    if (!isValidEmail) {
      dispatch({ type: 'validate_email' });
      return;
    }

    dispatch({ type: 'submit_start' });

    // Мокаем асинхронный запрос
    setTimeout(() => {
      if (state.password.length < 6) {
        dispatch({ type: 'submit_error', payload: 'Неверный пароль' });
      } else {
        dispatch({ type: 'submit_success' });
        alert('Вход выполнен успешно');
      }
    }, 1000);
  };

  return (
    <form onSubmit={handleSubmit} style={{ maxWidth: '300px', margin: 'auto' }}>
      <h2>Вход</h2>
      {state.error && <div style={{ color: 'red' }}>{state.error}</div>}
      <div>
        <label>Email:</label>
        <input
          type="text"
          value={state.email}
          onChange={(e) => dispatch({ type: 'change_email', payload: e.target.value })}
        />
      </div>
      <div>
        <label>Пароль:</label>
        <input
          type="password"
          value={state.password}
          onChange={(e) => dispatch({ type: 'change_password', payload: e.target.value })}
        />
      </div>
      <button type="submit" disabled={state.isLoading}>
        {state.isLoading ? 'Загрузка...' : 'Войти'}
      </button>
    </form>
  );
};

 

Экзаменационный билет №13

Теоретическая часть

  1. Объясните, что такое PureComponent и React.memo. В чём их отличие и когда следует использовать каждый из них?

  2. Что такое порталы в React и зачем они нужны? Приведите примеры использования.

 

Ответы на теоретическую часть:

 

  1. PureComponent — это базовый класс для классовых компонентов, реализующий метод shouldComponentUpdate() с поверхностным сравнением props и state. Он предотвращает ненужный рендер, если данные не изменились.

    React.memo — это Higher-Order Component, который применяется к функциональным компонентам и делает то же самое — сравнивает props и пропускает рендер, если они не изменились.

    Разница:

    • PureComponent работает с классовыми компонентами.
    • React.memo — с функциональными.
    • React.memo можно расширить, передав свою функцию сравнения вторым аргументом.
  2. Portals в React позволяют рендерить дочерние элементы вне иерархии родительского компонента в произвольном DOM-узле. Это особенно полезно для модальных окон, уведомлений, тултипов и других UI-компонентов, которые должны быть позиционированы вне текущего контекста CSS.
 

Практическая часть

Создайте компонент TabPanelпринимающий массив вкладокtabs и отображающий содержимое активной вкладки. Каждая вкладка должна иметь заголовок и содержимое. При клике на вкладку должно меняться состояние активной вкладки. Добавьте возможность отключения вкладок и стилизовать активную вкладку.

const TabPanel = ({ tabs }) => {
  const [activeIndex, setActiveIndex] = useState(0);

  const handleTabClick = (index) => {
    if (!tabs[index].disabled) {
      setActiveIndex(index);
    }
  };

  return (
    <div className="tab-panel">
      <div className="tab-list" role="tablist">
        {tabs.map((tab, index) => (
          <button
            key={index}
            role="tab"
            aria-selected={index === activeIndex}
            disabled={tab.disabled}
            onClick={() => handleTabClick(index)}
            className={`tab-button ${index === activeIndex ? 'active' : ''}`}
          >
            {tab.title}
          </button>
        ))}
      </div>
      <div className="tab-content" role="tabpanel">
        {tabs[activeIndex].content}
      </div>
    </div>
  );
};

// Пример использования:
function App() {
  const tabs = [
    {
      title: 'Вкладка 1',
      content: <p>Содержимое первой вкладки.</p>,
      disabled: false
    },
    {
      title: 'Вкладка 2',
      content: <p>Содержимое второй вкладки.</p>,
      disabled: false
    },
    {
      title: 'Заблокировано',
      content: <p>Эта вкладка отключена.</p>,
      disabled: true
    }
  ];

  return <TabPanel tabs={tabs} />;
}

 

Экзаменационный билет №14

Теоретическая часть

  1. Объясните, что такое React Context API и в каких сценариях её использование наиболее уместно. Какие ограничения имеет Context API?

  2. Что такое ленивая загрузка (lazy loading) компонентов в React? Как реализуется через React.lazy() и Suspense

 

Ответы на теоретическую часть:

    1. React Context API — это механизм передачи данных через дерево компонентов без необходимости явно передавать props на каждом уровне. Чаще всего используется для передачи глобального состояния, такого как тема приложения, данные авторизации, языковые настройки и т. д.

    Context состоит из:

    • React.createContext() — создаёт объект контекста.
    • Provider — компонент, который позволяет дочерним компонентам потреблять значение контекста.
    • Consumer или хук useContext — используется для чтения значения контекста.
  1. Ленивая загрузка (lazy loading) — это подход, при котором компоненты загружаются только при необходимости, например, при первом обращении к ним. Это улучшает производительность начальной загрузки приложения за счёт уменьшения объёма загружаемого JavaScript.
 

Практическая часть

Реализуйте пользовательский хук useFetchкоторый принимает URL и параметры запроса, и возвращает объект { data, loading, error }Хук должен выполнять fetch-запрос, обрабатывать ошибки и поддерживать отмену запроса при размонтировании компонента.

const useFetch = (url, options = {}) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;
    const abortController = new AbortController();

    const fetchData = async () => {
      try {
        const response = await fetch(url, {
          ...options,
          signal: abortController.signal
        });

        if (!response.ok) throw new Error(`Ошибка HTTP: ${response.status}`);

        const result = await response.json();

        if (isMounted) {
          setData(result);
          setLoading(false);
        }
      } catch (err) {
        if (isMounted && err.name !== 'AbortError') {
          setError(err.message);
          setLoading(false);
        }
      }
    };

    fetchData();

    return () => {
      isMounted = false;
      abortController.abort();
    };
  }, [url, options]);

  return { data, loading, error };
};

 

Экзаменационный билет №15

Теоретическая часть

  1. Что такое React.Fragment и зачем он используется? Приведите примеры использования и объясните, почему он предпочтительнее обёртки в виде <div>

  2. Охарактеризуйте работу хука useRefВ чём его отличие от useState и когда следует использовать?

 

Ответы на теоретическую часть:

  1. React.Fragment — это способ группировать несколько элементов JSX без добавления лишнего узла в DOM. Используется, когда нужно вернуть несколько элементов из компонента, но не хочется оборачивать их в дополнительный контейнер, например, <div>, который может нарушить структуру CSS или семантику HTML.
  2. Хук useRef возвращает изменяемый объект, свойство .current которого сохраняет своё значение между рендерами. Он полезен для:
    • Хранения ссылок на DOM-элементы ref={myRef}
    • Хранения любого значения, которое не должно вызывать повторный рендер при его изменении в отличие от useState
 

Практическая часть

Реализуйте пользовательский хук useDebounceкоторый принимает значение и задержку, и возвращает это значение с задержкой обновления. Хук должен быть полезен при реализации поиска с debounce, чтобы не отправлять запросы слишком часто.

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

(1) Кейс: "Реализация формы фильтрации товаров с debounce и валидацией"


Описание кейса

Вы работаете над интернет-магазином, где необходимо реализовать форму поиска и фильтрации товаров. Форма должна содержать:

  • Поле поиска по названию товара
  • Выпадающий список для выбора категории
  • Чекбокс "Только в наличии"
  • Кнопку "Сбросить фильтры"
 

Пользователь ожидает, что результаты поиска будут обновляться динамически при вводе текста или изменении фильтров. Однако вы замечаете, что при каждом нажатии клавиши выполняется новый HTTP-запрос, что вызывает перегрузку сервера и ухудшает отзывчивость интерфейса.

 

Проанализировать текущую реализацию, выявить проблемы с производительностью и UX, а также предложить и внедрить оптимизации:

  • Реализовать debounce для поля поиска
  • Обеспечить корректную работу формы без лишних запросов
  • Добавить валидацию и возможность сброса фильтров
 

Исходный скрипт 

const ProductFilter = ({ onApplyFilters }) => {
  const [filters, setFilters] = useState({
    searchQuery: '',
    category: 'all',
    inStockOnly: false,
  });

  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    const newValue = type === 'checkbox' ? checked : value;

    setFilters((prev) => ({
      ...prev,
      [name]: newValue,
    }));
  };

  const handleReset = () => {
    setFilters({
      searchQuery: '',
      category: 'all',
      inStockOnly: false,
    });
  };

  useEffect(() => {
    const fetchProducts = async () => {
      const response = await fetch(`/api/products?filters=${encodeURIComponent(JSON.stringify(filters))}`);
      const data = await response.json();
      onApplyFilters(data);
    };

    fetchProducts();
  }, [filters, onApplyFilters]);

  return (
    <form className="product-filter">
      <input
        type="text"
        name="searchQuery"
        placeholder="Поиск по названию..."
        value={filters.searchQuery}
        onChange={handleChange}
      />

      <select name="category" value={filters.category} onChange={handleChange}>
        <option value="all">Все категории</option>
        <option value="electronics">Электроника</option>
        <option value="clothing">Одежда</option>
      </select>

      <label>
        <input
          type="checkbox"
          name="inStockOnly"
          checked={filters.inStockOnly}
          onChange={handleChange}
        />
        Только в наличии
      </label>

      <button type="button" onClick={handleReset}>Сбросить фильтры</button>
    </form>
  );
};

 

Анализ ситуации и выявление проблем


Проблема №1: Отсутствие debounce для поискового запроса

При каждом нажатии клавиши происходит HTTP-запрос, что вызывает перегрузку сервера.

Решение:

Добавить пользовательский хук useDebounceчтобы откладывать выполнение запроса:

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
};

Использовать его в useEffect

const debouncedSearch = useDebounce(filters.searchQuery, 500);

useEffect(() => {
  // Выполняем запрос только если debouncedSearch изменился
}, [debouncedSearch]);

 

Проблема №2: Нет отмены предыдущего запроса при новом изменении

Старые запросы могут завершаться позже новых, приводя к некорректным данным.

Решение:

Использовать AbortControllerдля отмены предыдущего запроса:

useEffect(() => {
  const controller = new AbortController();

  const fetchData = async () => {
    try {
      const response = await fetch(`/api/products?filters=${JSON.stringify(filters)}`, {
        signal: controller.signal,
      });
      const data = await response.json();
      onApplyFilters(data);
    } catch (err) {
      if (err.name !== 'AbortError') {
        console.error('Ошибка загрузки:', err);
      }
    }
  };

  fetchData();

  return () => controller.abort();
}, [debouncedSearch, filters.category, filters.inStockOnly]);

 

Проблема №3: Форма не проверяет актуальность данных перед применением фильтров

Если значения фильтров совпадают с предыдущими — всё равно отправляется запрос.

 

Решение:

Сравнить текущие и предыдущие значения фильтров:

const prevFilters = usePrevious(filters); // реализация usePrevious ниже

if (isEqual(filters, prevFilters)) return;

Хук usePrevious

const usePrevious = (value) => {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
};

 

Проблема №4: Нет минимальной длины для поискового запроса

Запросы выполняются даже при вводе одной буквы, что может быть избыточно.

 

Решение:

Добавить условие:

if (debouncedSearch.length > 2 || debouncedSearch === '') {
  // Выполнить поиск
}

 

Проблема №5: Форма не блокирует ввод при загрузке данных

Пользователь может продолжать вводить, пока идёт загрузка — это может вызвать путаницу.

 

Решение:

Добавить состояние isLoadingи заблокировать элементы управления:

const [isLoading, setIsLoading] = useState(false);

// внутри fetchData
setIsLoading(true);
// после получения данных
setIsLoading(false);

<button disabled={isLoading} type="button" onClick={handleReset}>
  {isLoading ? 'Загрузка...' : 'Сбросить фильтры'}
</button>

 

Обучающие моменты

  • useDebounce — позволяет откладывать выполнение кода, например, при вводе текста.
  • AbortController — используется для отмены асинхронных операций, таких как HTTP-запросы.
  • usePrevious — помогает сохранять предыдущее значение состояния для сравнения изменений.
  • Оптимизация запросов — важно избегать лишних вызовов API, особенно при частых обновлениях фильтров.
  • Управление состоянием формы — лучше централизованно управлять через useStateособенно если форма содержит несколько зависимых полей.
 

Дополнительные задания для самостоятельной работы

  1. Реализуйте кэширование результатов поиска
    Сохраняйте уже выполненные запросы и возвращайте закэшированный результат при повторном использовании тех же фильтров.

  2. Добавьте индикатор загрузки рядом с полем поиска
    Отображайте спиннер или надпись "Идет поиск..." при выполнении запроса.

  3. Перепишите логику с использованием React Query или SWR
    Замените ручное управление состояния и эффектов на готовое решение для управления данными.

  4. Добавьте поддержку пагинации
    Реализуйте кнопки "Предыдущая/Следующая страница" и обновляйте параметры запроса.

  5. Добавьте валидацию категории перед отправкой запроса
    Если категория не существует, показывайте ошибку вместо запроса.

  6. Сделайте форму контролируемой через URL-параметры
    При открытии страницы с определёнными параметрами?search=iphone&category=electronicsавтоматически устанавливайте соответствующие фильтры.

  7. Реализуйте локальное хранение фильтров в localStorage
    При перезагрузке страницы восстанавливайте последние установленные значения фильтров.

 

(2) Кейс: "Реализация темизации (light/dark mode) с сохранением состояния в localStorage"


Описание ситуации

Вы работаете над веб-приложением, которое должно поддерживать две темы — светлую и тёмную. Пользователь должен иметь возможность переключать тему в интерфейсе, а его выбор должен сохраняться между сессиями.

 

На данный момент:

  • В интерфейсе есть кнопка переключения темы.
  • Тема применяется к компонентам через CSS-класс на корневом элементе.
  • При перезагрузке страницы тема всегда сбрасывается на стандартную (например, light).
 

Ваша задача — реализовать устойчивое управление темой приложения с сохранением состояния и синхронизацией между компонентами.

Цель кейса

  1. Реализовать переключение темы (light/dark).
  2. Сохранить выбор пользователя в localStorage
  3. Применить тему при монтировании компонента.
  4. Обеспечить доступ к текущей теме из любого компонента приложения.

Проблема №1: Нет сохранения выбора темы между перезагрузками страницы.

 

Решение:

Используйте localStorage для хранения текущей темы:

localStorage.setItem('app-theme', theme);

При монтировании компонента считывайте значение:

const savedTheme = localStorage.getItem('app-theme');
if (savedTheme) setTheme(savedTheme);

 

Проблема №2: Тема не применяется глобально, а дублируется в разных компонентах.

 

Решение:

Создайте провайдер с помощью Context APIчтобы централизованно управлять темой:

<ThemeProvider>
  <App />
</ThemeProvider>

 

Доступ к теме из любого компонента через кастомный хук:

const { theme, setTheme } = useTheme();

 

Проблема №3: Тема не реагирует на системные настройки пользователя (например, dark mode ОС).

 

Решение:

Проверьте предпочтения системы через matchMedia API

const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (!savedTheme && systemPrefersDark) setTheme('dark');

 

Проблема №4: Изменение темы не отражается в интерфейсе (CSS не обновляется).

 

Решение:

Добавляйте/удаляйте CSS-классы на корневом элементе при изменении темы:

useEffect(() => {
  document.documentElement.classList.remove('light', 'dark');
  document.documentElement.classList.add(theme);
}, [theme]);

 

Проблема №5: Нет удобного способа получения текущей темы в любом компоненте.

 

Решение:

Создайте кастомный хук useTheme()

export const useTheme = () => {
  const context = React.useContext(ThemeContext);
  if (!context) throw new Error('useTheme должен использоваться внутри ThemeProvider');
  return context;
};

 

Проблема №6: Нет кнопки переключения темы или она работает некорректно.

Решение:

Реализуйте простую кнопку:

<button onClick={toggleTheme}>
  {theme === 'light' ? 'Тёмная тема' : 'Светлая тема'}
</button>

Функция toggleThemeменяет тему:

setTheme(theme === 'light' ? 'dark' : 'light');

 

Проблема №7: Пользователь не видит, какая тема активна (нет визуального индикатора).

Решение:

Добавьте стилизованный индикатор или текст:

<div>Текущая тема: {theme}</div>

Или иконку солнца/луны:

{theme === 'light' ? '☀️' : '🌙'}

 

Обучающие моменты

  • Context API — удобный инструмент для централизованного управления состоянием темы.
  • localStorage — позволяет сохранять выбор пользователя между сессиями.
  • matchMedia API — считывает системные настройки темы и применяет их по умолчанию.
  • CSS-классы на html
    body
    — простой способ стилизовать разные темы через CSS.
  • Кастомный хук useTheme — упрощает доступ к теме из любого компонента.
  • Подписка на изменения системных предпочтений — повышает пользовательский опыт.
  • Оптимизация рендера — тема не должна вызывать лишних перерисовок.
 

Дополнительные задания для самостоятельной работы

  1. Добавьте автоматическое обновление темы при изменении системных настроек

    • Используйте window.matchMedia().addEventListener
  2. Реализуйте более 2 тем

    • Добавьте, например, "синюю" или "высокой контрастности".
  3. Сохраните тему в IndexedDB вместо localStorage

    • Это улучшит производительность при работе с большим объемом данных.
  4. Изменяйте тему через CSS-переменные

    • Реализуйте набор переменных для каждой темы в :root
  5. Сделайте тему частью глобального состояния (Redux / Zustand / Recoil)

    • Интегрируйте в уже существующее управление состоянием.

Ролевая игра №1: «React-Стартап: Создание MVP за 2 недели»


Цель игры:

Научить студентов работать в команде, проектировать архитектуру приложения, разрабатывать фронтенд на React с использованием современных практик и библиотек, а также представлять результаты своей работы перед заказчиком.

 

Формат игры:

  • Тип: Командная ролевая игра
  • Длительность: 2 недели (по 3–4 академических часа в неделю)
  • Количество участников: 4–6 человек в команде
  • Минимальное количество игроков: 4
  • Преподаватель: выступает в роли "заказчика" и "наставника"
 

Сеттинг:

Вы — молодая IT-стартап-команда, которая получила задание от инвестора (преподавателя) создать MVP (минимально жизнеспособный продукт) за ограниченное время. Ваша задача — спроектировать, реализовать и презентовать прототип приложения на основе технического задания.

 

Роли в команде:

Роль
Обязанности
Product Owner
Согласует требования с заказчиком, уточняет ТЗ, принимает решения по приоритетам
Frontend Lead
Отвечает за архитектуру приложения, выбор технологий и библиотек (React, Router, Redux и т.д.)
UI/UX Designer
Создаёт макеты интерфейсов, работает над пользовательским опытом
Developer (x2)
Пишут компоненты, реализуют логику, работают с API, тестами
QA / Tester (опционально)
Пишет тесты, проверяет функционал

 

 


Этапы игры:

1. Постановка задачи 
  • Получение ТЗ от преподавателя.
  • Анализ требований, составление списка фич.
  • Распределение ролей в команде.
 
2. Проектирование 
  • Создание wireframe’ов.
  • Проектирование структуры приложения (компоненты, роуты, стор).
  • Выбор технологий (React, TypeScript, CSS-in-JS и т.д.).
 
3. Разработка MVP 
  • Реализация базового функционала:
    • Навигация
    • Формы
    • Данные (mock или API)
    • Темизация
    • Адаптивность
 
4. Тестирование и оптимизация 
  • Unit- и snapshot-тесты.
  • Оптимизация производительности.
  • Устранение найденных ошибок.
 
5. Презентация и защита 
  • Презентация MVP клиенту (преподавателю).
  • Демонстрация ключевых возможностей.
  • Ответы на вопросы.
  • Обратная связь от "инвестора".
 

Обучающие эффекты:

Эффект
Описание
Командная работа
Работа в условиях ограниченного времени и ресурсов
Реальный цикл разработки
От идеи до MVP, включая проектирование, реализацию и презентацию
Практические навыки React
Реализация форм, состояния, маршрутов, темизации, API
Адаптивность к изменениям
Работа с изменяющимся ТЗ
Участие в презентации
Развитие soft skills и навыков демонстрации решений
Работа с реальными библиотеками
Использование популярных инструментов: React Query, Formik, Router, Testing Library

Возможные проблемы и вызовы во время игры:

Проблема
Как решить
Разногласия в команде
Назначение Product Owner для принятия решений
Нехватка времени
Итеративная разработка, MVP-подход
Непонятное ТЗ
Встреча с "заказчиком" для уточнения
Технические сложности
Наставник (преподаватель) помогает советом и примером
Зависимость от одного участника
Регулярные чекины внутри команды
Перегрузка некоторых участников
Четкое распределение задач и ответственности

 

Ролевая игра №2: «Bug Hunter: Охота за багами в legacy-приложении»


Цель игры:

Научить студентов читать и понимать существующий код, находить и исправлять ошибки, работать с устаревшими практиками и документировать технический долг. Развить навыки анализа, рефакторинга и тестирования.

 

Формат игры:

  • Тип: Командная/индивидуальная ролевая игра
  • Длительность: 1 неделя (по 3–4 академических часа)
  • Количество участников: 2–4 человека в команде или индивидуально
  • Минимальное количество игроков: 1
  • Преподаватель: выступает в роли "техлида" и "заказчика"
 

Сеттинг:

Вы — группа опытных разработчиков, приглашённых в компанию для восстановления фронтенд-части критически важного внутреннего приложения. Приложение было написано несколько лет назад, документации почти нет, оригинальная команда давно уволена. Ваша задача — найти и исправить баги, провести минимальный рефакторинг и подготовить отчёт по состоянию проекта.

 

Роли в команде:

Роль
Обязанности
Tech Lead
Определяет приоритеты, распределяет задачи, принимает решения по архитектуре
Code Analyst
Изучает логику работы приложения, ищет причины багов
QA / Bug Hunter
Воспроизводит ошибки, пишет тесты, проверяет исправления
Refactor Engineer
Выполняет рефакторинг, улучшает читаемость и поддерживаемость кода

 


Этапы игры:

1. Получение задания 
  • Получение доступа к "legacy-приложению" (готовый React-проект с намеренными багами).
  • Знакомство с минимальной документацией (или её отсутствием).
  • Постановка задач на неделю: найти N багов, написать тесты, провести рефакторинг.
 
2. Анализ и диагностика 
  • Изучение структуры проекта.
  • Поиск первых багов (визуальные, логические, состояние, рендеринг).
  • Написание простых unit- и snapshot-тестов.
 
3. Исправление и рефакторинг 
  • Исправление найденных багов.
  • Упрощение сложных частей кода.
  • Переписывание некоторых частей на современные паттерны (например, замена классовых компонентов на хуки).
  • Добавление типизации (если проект без TypeScript).
 
4. Тестирование и отчетность 
  • Написание дополнительных тестов.
  • Подготовка отчёта: какие баги были найдены и исправлены, что можно улучшить, какие части требуют переписывания.
  • Предложение доработок и модернизации проекта.
 
5. Защита решения 
  • Презентация изменений перед "заказчиком".
  • Ответы на вопросы по реализации и обоснованию решений.
  • Получение обратной связи от преподавателя.
 

Обучающие эффекты:

Эффект
Описание
Работа с legacy-кодом
Навык понимания старого кода, написанного другими разработчиками
Чтение чужого кода
Анализ и интерпретация логики без явной документации
Поиск и устранение багов
Диагностика проблем, использование DevTools и логов
Написание тестов
Покрытие кода тестами для предотвращения регрессии
Рефакторинг
Улучшение читаемости и поддерживаемости без полной переписки
Работа в условиях неопределенности
Нестандартные ситуации, плохой код, отсутствие документации

Возможные проблемы и вызовы во время игры:

Проблема
Как решить
Сложно понять, как работает код
Использовать консоль-логи, React Developer Tools, пошаговое изучение
Баг сложно воспроизвести
Написание тестов для точного воспроизведения
Конфликты в команде
Четкое разделение задач, регулярные короткие встречи
Неочевидные ошибки
Обсуждение в группе, обращение к наставнику
Технический долг мешает дальнейшей работе
Составление списка рекомендаций для последующего этапа развития продукта

 

Ролевая игра №3: «React-конференция: защита архитектурного решения»


Цель игры:

Научить студентов проектировать масштабируемые React-приложения, обосновывать выбор архитектурных решений, отвечать на технические вопросы и презентовать сложные идеи в понятной форме.

 

Формат игры:

  • Тип: Групповая ролевая игра с элементами публичной защиты
  • Длительность: 5–7 дней (в зависимости от глубины реализации)
  • Количество участников: 3–5 человек в команде
  • Минимальное количество игроков: 1 команда
  • Преподаватель и/или студенты выступают в роли "техэкспертов" или "инвесторов"
 

Сеттинг:

Вы — группа фронтенд-разработчиков, приглашённых на внутреннюю конференцию компании. Вам предстоит представить своё решение для нового корпоративного приложения, объяснить, почему выбранная архитектура оптимальна, и ответить на вопросы экспертов. Конкурирующие команды также могут защищать свои версии решений. Побеждает та команда, чье решение будет признано наиболее устойчивым, читаемым и поддерживаемым.

 

Роли в команде:

Роль
Обязанности
Архитектор
Отвечает за общую структуру приложения, выбор шаблонов и библиотек
Lead Developer
Реализует ключевые части архитектуры, следит за качеством кода
Tech Writer / Documenter
Подготавливает документацию, презентационные материалы, диаграммы
Presenter
Ведёт презентацию перед экспертами
QA Engineer (опционально)
Тестирует подход, задаёт вопросы по надёжности и покрытию тестами

 


Этапы игры:

1. Получение технического задания 
  • Получение задачи: разработать архитектуру React-приложения на основе ТЗ.
  • Пример: интернет-магазин, CRM-система, платформа управления проектами.
  • Команды получают минимальный функционал, но должны самостоятельно продумать архитектуру.
 
2. Проектирование архитектуры 
  • Выбор библиотек: React, Router, Redux, Zustand, Query, Form и т.д.
  • Разработка структуры проекта (feature-sliced, domain-driven, etc.)
  • Создание диаграмм (компонента, стор, данные, маршруты)
  • Документация решения
 
3. Реализация MVP архитектуры 
  • Создание минимальной структуры проекта
  • Реализация базовых модулей
  • Примеры использования ключевых частей архитектуры
  • Написание минимального набора тестов
 
4. Подготовка презентации 
  • Создание слайдов
  • Подготовка демонстрации
  • Практика выступления, репетиция ответов на вопросы
 
5. Защита решения 
  • Презентация своей архитектуры
  • Обоснование выбора решений
  • Ответы на вопросы от "экспертного совета"
  • Сравнение с решениями других команд
 

Обучающие эффекты:

Эффект
Описание
Проектирование архитектуры
Умение планировать структуру проекта заранее
Обоснование решений
Навык объяснять выбор технологий и паттернов
Работа в команде
Совместная разработка и распределение задач
Участие в технических обсуждениях
Ответы на сложные вопросы, защита своего мнения
Презентация решений
Навыки коммуникации, устного выступления и демонстрации решений
Работа с документацией
Составление технической документации и схем

Возможные проблемы и вызовы во время игры:

Проблема
Как решить
Неопределенность в ТЗ
Задавать уточняющие вопросы до начала проектирования
Нехватка времени на реализацию
Фокус на архитектуре, а не полной реализации
Сложность обоснования выбора
Изучение best practices и примеров из реальных проектов
Сложности в презентации
Репетиция перед другими студентами
Конфликты в команде
Четкое распределение ролей и задач
Несогласие с экспертами
Развитие soft skills: аргументация, работа с критикой

Технические аспекты :

  • Использование Context API , Redux Toolkit , Zustand или других инструментов
  • Реализация feature-sliced design или другой архитектурной парадигмы
  • Поддержка TypeScript
  • Стилизация через CSS-in-JS , Tailwind , BEM и т.д.
  • Роутинг через React Router
  • Асинхронные запросы через RTK Query , SWR , Axios + хуки
  • Покрытие тестами (Jest, RTL)
 

Ролевая игра №4: «Frontend под давлением: экстренная правка production’а»


Цель игры:

Научить студентов работать в условиях стресса и срочности, быстро находить и исправлять критические ошибки в продакшн-приложении, принимать решения под давлением и коммуницировать в чрезвычайной ситуации.

 

Формат игры:

  • Тип: Ситуационная командная ролевая игра
  • Длительность: 1–2 дня (интенсив)
  • Количество участников: 3–5 человек в команде
  • Минимальное количество игроков: 1
  • Преподаватель выступает в роли "менеджера", "техлида" или "паникующего клиента"
 

Сеттинг:

Приложение компании вышло в production. Уже через несколько часов после запуска начались жалобы от пользователей:

  • Кнопки не работают
  • Формы не отправляются
  • Данные не загружаются
  • Приложение падает на мобильных устройствах
 

Вам нужно срочно разобраться в происходящем, найти и исправить критические баги, восстановить стабильность и дать обратную связь руководству — всё это за очень ограниченное время.

 

Роли в команде:

Роль
Обязанности
Tech Lead
Организует работу, распределяет задачи, принимает ключевые технические решения
Bug Hunter
Ищет и воспроизводит баги, работает с DevTools и логами
Hotfix Developer
Пишет минимальные, но эффективные исправления
Communicator / PM (опционально)
Сообщает руководству о прогрессе, пишет сообщения в чат поддержки, готовит отчёт
QA Engineer (опционально)
Тестирует исправления, проверяет регрессию

 


Этапы игры:

1. Аварийный вызов 
  • Получение уведомления о критических проблемах в production.
  • Быстрое ознакомление с проектом (готовый React-проект с намеренными ошибками).
  • Анализ первых сигналов: Sentry, console.log, пользовательские жалобы.
 
2. Идентификация проблемы
  • Воспроизведение багов.
  • Поиск корневых причин: что сломано, где, почему.
  • Назначение приоритетов: какие баги критичны, а какие могут подождать.
 
3. Горячие исправления 
  • Проведение минимального рефакторинга.
  • Исправление критических багов.
  • Запуск тестов и проверка на производительность.
  • Подготовка hotfix-версии.
 
4. Отчет и презентация решений 
  • Ответы на вопросы от "руководства".
  • Объяснение, почему произошла ошибка.
  • Предложения по предотвращению подобных ситуаций в будущем.
  • Возможная защита своего подхода перед "комиссией".
 

Обучающие эффекты:

Эффект
Описание
Работа в условиях стресса
Научиться действовать быстро и хладнокровно при высокой нагрузке
Поиск критических багов
Диагностика и исправление серьезных проблем в коде
Оценка приоритетов
Умение отличать критический баг от второстепенной проблемы
Командная работа под давлением
Совместная диагностика и быстрая реакция
Коммуникация с непрофессионалами
Умение объяснять технические проблемы простым языком
Работа с готовыми проектами
Изучение чужого кода, понимание логики без документации

Возможные проблемы и вызовы во время игры:

Проблема
Как решить
Баг сложно воспроизвести
Использовать инструменты отладки, логи, тесты
Конфликты в команде из-за времени
Четкое разделение задач и временные рамки
Неочевидные ошибки (например, race condition)
Обсуждение в группе, обращение к наставнику
Сложно понять, как работает старый код
Использовать DevTools, React Profiler, console.log
Ошибки мешают друг другу
Разделение задач, использование feature flags или временных обходных решений

Примеры технических проблем (багов), которые можно использовать:

  • useEffect с неправильным массивом зависимостей → бесконечный цикл запросов
  • setState внутри рендера → ошибка Maximum update depth exceeded
  • Неправильное управление формами → данные не сохраняются
  • Ленивая загрузка компонентов без Suspense → белый экран
  • Некорректная типизация → runtime-ошибки
  • Лишние перерисовки → зависание интерфейса
  • Ошибки в API-запросах → некорректная обработка ошибок, падение UI

 

Интеллект-карта 1: Общий путь освоения React (Профессиональный уровень)

Ветки:

  • Основы React

    • JSX
    • Компоненты (функциональные и классовые)
    • Props и их типизация (PropTypes, TypeScript)
    • Условный рендеринг и списки
  • Состояние и жизненный цикл

    • useState, useEffect
    • Работа с DOM через useRef
    • useReducer для сложного состояния
    • Контролируемые / неконтролируемые компоненты
  • Работа с формами

    • Валидация
    • Реактивное обновление
    • Хранение состояния формы
    • Библиотеки: Formik, React Hook Form
  • Оптимизация производительности

    • React.memo
    • useCallback и useMemo
    • Порталы и Suspense
    • Ленивая загрузка (React.lazy)
  • Управление состоянием

    • Context API
    • Redux Toolkit
    • Zustand / MobX (по выбору)
    • Асинхронные эффекты (RTK Query, Thunk, Saga)
  • Роутинг

    • React Router (v6/v7)
    • Динамические маршруты
    • Защита маршрутов
    • Lazy loading страниц
  • Тестирование

    • Unit-тесты (Jest, React Testing Library)
    • Snapshot тесты
    • Тестирование хуков и компонентов
    • End-to-end тесты (Cypress, Playwright)
  • Темизация и локализация

    • Темизация через Context API или CSS переменные
    • i18n библиотеки (react-i18next, formatjs)
    • Поддержка RTL
  • Архитектура приложений

    • Разделение кода
    • Слои: UI / Features / Entities / Shared
    • Feature sliced design
    • Модульность и переиспользуемость
  • Деплой и CI/CD

    • Build-процесс (Webpack, Vite)
    • Оптимизация сборки
    • Деплой на Vercel, Netlify, GitHub Pages
    • Настройка CI/CD (GitHub Actions, GitLab CI)
 

Интеллект-карта 2: Практические навыки и проекты

Ветки:

  • Мини-проекты

    • Форма регистрации с валидацией
    • Список задач (To-do list)
    • Калькулятор
    • Погода (API + темизация)
  • Средние проекты

    • Интернет-магазин (каталог, корзина, фильтры)
    • Чат-приложение (с WebSocket или Firebase)
    • Блог с админкой
    • Расписание занятий (drag & drop, календарь)
  • Большой проект (Capstone)

    • SPA с авторизацией (JWT, OAuth)
    • CRUD-операции
    • Роутинг и защита маршрутов
    • Тестирование и документация
    • Деплой и оптимизация
 

Интеллект-карта 3: Инструменты и технологии

Ветки:

  • JavaScript / TypeScript

    • ES6+ синтаксис
    • Async/await, Promises
    • Работа с массивами и объектами
    • TypeScript (типы, интерфейсы, generics)
  • Build Tools

    • Webpack
    • Vite
    • Babel
    • ESLint / Prettier
  • CSS и стилизация

    • CSS-in-JS (styled-components, emotion)
    • Tailwind CSS
    • BEM / SMACSS
    • Анимации (Framer Motion, React Spring)
  • HTTP клиенты

    • Axios
    • Fetch API
    • SWR / React Query
    • RTK Query
  • Тестирование

    • Jest
    • React Testing Library
    • Cypress / Playwright
    • Testing Library DOM
  • Инструменты разработки

    • DevTools
    • React Developer Tools
    • Storybook / Chromatic
    • Linter, Formatter
 

Интеллект-карта 4: Профиль профессионального React-разработчика

Ветки:

  • Hard Skills

    • Знание React Core
    • Умение работать с асинхронностью
    • Написание чистого, поддерживаемого кода
    • Понимание принципов DRY, KISS, SOLID
    • Опыт работы с REST / GraphQL API
  • Soft Skills

    • Самостоятельная работа
    • Работа в команде
    • Чтение документации
    • Решение проблем
    • Презентация решений
  • Профессиональное развитие

    • Изучение новых версий React (например, React 19, React Compiler)
    • Участие в open-source
    • Создание портфолио
    • Подготовка к техническим собеседованиям

1. "React — Разработка веб-приложений" — Кайс Насир

  • Тип: Учебное пособие
  • Краткое описание:
    Подробное руководство по созданию современных SPA с использованием React. Охватывает от базовых концепций до продвинутых паттернов, хуков, контекста, роутинга и Redux.
  • Для кого: Для студентов и начинающих разработчиков.
 

2. "React. Полное руководство" — Максимilian Шварценбах (Maximilian Schwarzmüller)

  • Тип: Учебник
  • Краткое описание:
    Один из самых популярных курсов и книг по React. Подходит как практическое пособие по всем аспектам фреймворка: компоненты, состояние, хуки, тестирование, оптимизация, TypeScript и т.д.
  • Плюс: Видеокурс в дополнение к книге.
 

3. "React Design Patterns and Best Practices" — Michele Bertoli

  • Тип: Научно-популярная / методическая литература
  • Краткое описание:
    Книга о проектировании приложений на React. Рассмотрены лучшие практики, шаблоны проектирования, работа с формами, стилизацией и архитектурой.
  • Для кого: Продвинутые разработчики, преподаватели, менторы.
 

4. "Learning React: Functional UI Development" — Alex Banks, Eve Porcello

  • Тип: Учебное пособие
  • Краткое описание:
    Практический курс по созданию интерфейсов с нуля. Покрывает JSX, компоненты, работу с данными, клиентский роутинг и интеграцию с API.
  • Плюс: Подходит для обучения в академической среде.
 

5. Методические указания «Разработка одностраничных приложений на React» (авторские материалы вузов или онлайн-курсов)

  • Тип: Методическое пособие
  • Краткое описание:
    Специализированные лабораторные работы, задачники и практические задания по темам:
    • Создание компонентов
    • Управление состоянием
    • Роутинг
    • Формы и валидация
    • Тестирование
  • Где найти: Внутренние учебные материалы курсов по фронтенд-разработке (например, Яндекс.Практикум, Coursera, Skillbox).
  1. React Профессионал: Современная фронтенд-разработка с нуля до PRO
  2. React Fullstack Developer: Полный путь к профессии
  3. Мастер React: Профессиональная разработка интерфейсов
  4. Фронтенд-разработчик на React: Продвинутый уровень
  5. React Pro: Архитектура, оптимизация, производительность
  6. React в продакшене: Реальные практики опытного разработчика
  7. Профессиональный React: Разработка масштабируемых приложений
  8. React Developer Bootcamp: Интенсив по профессиональному уровню
  9. React. Уровень PRO: Масштабирование, тестирование, CI/CD
  10. React-архитект: Паттерны, дизайн-системы, управление состоянием
  11. Фронтенд на React: От Junior до Middle за 3 месяца
  12. React Advanced: Глубокое погружение в сложные темы
  13. React в реальных проектах: Кейсы, задачи, решения
  14. React для профессионалов: Продвинутые хуки, SSR, микросервисы
  15. React-мастерство: Тестирование, деплой, оптимизация
  16. React. Путь Senior’а: Архитектура, чистый код, шаблоны
  17. Разработка UI на React: Стилизация, компоненты, дизайн-системы
  18. React в команде: Best practices, документация, совместная работа
  19. React с TypeScript: Типизация в крупных приложениях
  20. React и экосистема: Redux, Router, Query, Formik и другие библиотеки
  21. SPA на React: Создание одностраничных приложений уровня PRO
  22. React для продвинутых: Ленивая загрузка, роутинг, серверный рендер
  23. React-инженер: Производительность, безопасность, доступность
  24. React-паттерны: Профессиональное проектирование интерфейсов
  25. React в Agile: Разработка интерфейсов в условиях динамических требований
 

 

Заявка ученика, студента, слушателя
Заявка преподавателя, репетитора админу сети.
18:32
11
Посещая этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.