Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. JSX и типизированные компоненты
jsx_components

JSX и типизированные компоненты

JSX как выражение, чистые функции-компоненты, props, children, списки, ключи и безопасная композиция.

Открыть лабораториюv0.1.0Запускается локально из публичного репозитория

JSX и типизированные компоненты

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

#Результат урока

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

До начала достаточно строгий TypeScript, функции, массивы и неизменяемые преобразования. В конце должен появиться не конспект, а типизированный каталог с семантической разметкой, устойчивыми ключами и переиспользуемыми slots.

#1. JSX — выражение, а не строковый HTML

JSX компилируется в создание React elements. Фигурные скобки вставляют значение выражения; строки экранируются React DOM, поэтому обычный текст не становится HTML. Теги в нижнем регистре означают intrinsic DOM elements, а имя с заглавной буквы — ссылку на компонент. Возвращаемое дерево должно иметь один корневой element или Fragment.

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

type GreetingProps = { name: string }; export function Greeting({ name }: GreetingProps) { return <p>Здравствуйте, {name}</p>; }

Если name содержит <script>, React отобразит текст. Для интерпретации HTML нужен отдельный опасный API, который рассматривается в теме безопасности.

Рабочая проверка. Передайте строку с HTML-символами и проверьте, что она отображается как текст.

Типичная поломка. Склеивать пользовательские данные в HTML-строку и вставлять через DOM API.

#2. Чистая функция-компонент

Во время render компонент читает props, state и context и возвращает описание UI. Он не должен менять внешние переменные, отправлять запросы, подписываться или мутировать полученные объекты. Чистота позволяет React повторить, прервать или отбросить render без внешних последствий. Пользовательские действия выполняются в handlers, синхронизация с внешней системой — в Effect или framework boundary.

Рабочая проверка. Отрендерите компонент дважды с одинаковыми входами и проверьте отсутствие новых записей в внешнем массиве.

Типичная поломка. Отправлять аналитику или изменять cache непосредственно в теле компонента.

#3. Props как публичный контракт

Props описывают минимальный вход компонента. Не передавайте огромный доменный объект, если компонент использует два поля: это расширяет связь и усложняет переиспользование. Обработчики называют по намерению (onArchive), а DOM-event тип оставляют внутри leaf-компонента. Значения по умолчанию задают при деструктуризации.

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

type StatusBadgeProps = { label: string; tone?: 'neutral' | 'success' | 'danger'; }; export function StatusBadge({ label, tone = 'neutral' }: StatusBadgeProps) { return <span data-tone={tone}>{label}</span>; }

Литеральный union ограничивает варианты, а optional prop действительно может отсутствовать. null не добавляется автоматически.

Рабочая проверка. Попробуйте передать неизвестный tone и убедитесь, что ошибка возникает у потребителя компонента.

Типичная поломка. Принимать user: any и читать произвольные поля глубоко внутри визуального компонента.

#4. Типы children и slots

ReactNode описывает широкий набор отображаемых children: elements, строки, числа, null и коллекции. ReactElement уже и полезен, если нужен именно element для клонирования или инспекции, хотя такая связь часто хрупка. Named slots через props делают структуру явной: header, actions, children. Не добавляйте children автоматически, если компонент их не поддерживает.

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

type PanelProps = { title: string; actions?: React.ReactNode; children: React.ReactNode; }; export function Panel({ title, actions, children }: PanelProps) { return <section><header><h2>{title}</h2>{actions}</header>{children}</section>; }

Slots позволяют родителю передать поведение и разметку, не превращая Panel в компонент со множеством бизнес-флагов.

Рабочая проверка. Соберите две панели с разными действиями, не меняя реализацию Panel.

Типичная поломка. Добавлять boolean props showEdit, showDelete, showExport для каждой новой кнопки.

#5. Списки и стабильные keys

key сообщает React идентичность sibling-элемента между render. Он должен быть стабильным и уникальным среди соседей, происходить из данных и не генерироваться во время render. Индекс подходит только для действительно статичного списка без вставок, удаления и перестановки; иначе локальное состояние и DOM могут переехать к другой записи.

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

export function ProductList({ products }: { products: readonly Product[] }) { return <ul>{products.map(product => <ProductRow key={product.id} product={product} /> )}</ul>; }

key не попадает в ProductRow как обычный prop. Если идентификатор нужен внутри, передайте id отдельно.

Рабочая проверка. Введите текст в строке, переставьте товары и проверьте, что текст остаётся у правильного id.

Типичная поломка. Использовать индекс или Math.random() как key изменяемого списка.

#6. Композиция вместо наследования

React-компоненты обычно расширяют поведением через props, children и специализированные wrappers, а не через классовое наследование визуальных компонентов. Контейнер отвечает за layout, feature-компонент — за сценарий, leaf — за DOM. Чем ниже граница, тем меньше она должна знать о маршрутах, кэше и авторизации.

Рабочая проверка. Разделите страницу на data owner, feature composition и чистую визуальную таблицу.

Типичная поломка. Создать BasePage с десятками virtual hooks и скрытым жизненным циклом.

#7. ref как prop в React 19

В React 19 function component может получать ref как prop; forwardRef больше не нужен для нового кода и планируется к устареванию. Ref — escape hatch к DOM или императивному handle, а не альтернативный канал данных. Типизируйте конкретный Ref<HTMLInputElement> и сохраняйте обычный controlled flow для значений.

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

type SearchInputProps = React.ComponentPropsWithRef<'input'> & { label: string; }; export function SearchInput({ label, ref, ...inputProps }: SearchInputProps) { return <label>{label}<input ref={ref} {...inputProps} /></label>; }

ComponentPropsWithRef сохраняет нативные input props и правильный тип ref. Распространяйте props осознанно, чтобы не переписать защищённые атрибуты.

Рабочая проверка. Сфокусируйте поле после явного пользовательского действия через типизированный ref.

Типичная поломка. Хранить текущее значение input только в ref.current.value и ожидать реактивного render.

#8. Типы компонентов без ритуалов

Обычная именованная функция с типизированным параметром props обычно даёт лучший вывод и понятные generics. React.FC допустим, но не обязателен и не делает компонент правильнее. Возвращаемый тип часто стоит вывести; явный ReactNode нужен, если API действительно допускает текст или null. Type-only imports уменьшают неоднозначность между runtime и типами.

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

import type { ReactNode } from 'react'; type WhenProps = { condition: boolean; children: ReactNode }; export function When({ condition, children }: WhenProps) { return condition ? children : null; }

Функция может вернуть ReactNode; современная связка React types и TypeScript корректно моделирует такой компонент.

Рабочая проверка. Сравните диагностику generic-компонента, объявленного обычной function и через чрезмерно широкую аннотацию.

Типичная поломка. Добавлять React.FC<any> ко всем компонентам, считая это типобезопасностью.

#Лаборатория

Реализуйте ProductList, карточку товара и панель действий. Данные приходят как readonly-модель, список поддерживает перестановку, пустое состояние и пользовательский slot действий. Проверьте семантику и сохранение локального состояния строк.

Критерий завершения: компоненты чисты, публичные props не разрешают незаконные сочетания, а reorder не переносит состояние между товарами. Сначала зафиксируйте наблюдаемое поведение тестом или измерением, затем меняйте реализацию.

#Источники для сверки

  • React: Describing the UI
  • React: Passing Props
  • React: Rendering Lists
  • React 19 ref as prop

Устранение неисправностей

Проверьте свои знания

Вопросы ещё не добавлены

Вопросы для этой подтемы ещё не добавлены.

Далее: Модель рендеринга React