Компоненты, props и JSX
Чистые компоненты, правила JSX, key в списках и композиция через children.
Обновлено
Что такое React
React — библиотека для построения интерфейсов из компонентов. Главная идея: UI = f(state) — вы описываете, как выглядит интерфейс для неких данных, а когда данные меняются, React сам обновляет DOM.
| Императивно (DOM напрямую) | Декларативно (React) |
|---|---|
«найди список, создай li, вставь текст, добавь» |
«для этого массива список выглядит так» |
| вы сами помните, что на экране | React сравнивает и применяет только разницу |
Что такое компонент
Компонент — это функция, которая возвращает интерфейс (JSX). Пишете один раз и используете как собственный HTML-тег сколько угодно раз.
type Props = { name: string; role?: 'admin' | 'user' }
export function UserBadge({ name, role = 'user' }: Props) {
return <span className="badge">{name} · {role}</span>
}
<UserBadge name="Ana" role="admin" />
<UserBadge name="Ivan" />- Имя начинается с заглавной буквы — иначе React считает это HTML-тегом.
- Получает props — данные от родителя, как аргументы.
- Props только для чтения: внутри компонента их никогда не меняют.
- Должен быть чистым: одни и те же props → один и тот же JSX, без побочных эффектов во время рендера.
Что такое JSX
JSX — синтаксис, похожий на HTML, но это JavaScript: <Card title="x" /> превращается в вызов функции. Отличия от HTML:
| HTML | JSX | Почему |
|---|---|---|
class |
className |
class — зарезервированное слово в JS |
for |
htmlFor |
то же самое |
onclick="..." |
onClick={fn} |
camelCase, передаётся функция |
style="color: red" |
style={{ color: 'red' }} |
объект JS |
<br> |
<br /> |
все теги закрываются |
| несколько элементов в корне | один корень или <>...</> (фрагмент) |
функция возвращает одно значение |
Внутри {} можно писать любое выражение JS: переменные, вызовы, тернарные операторы, map.
Условный рендер — варианты
| Вариант | Когда |
|---|---|
{isAdmin && <Panel />} |
показать или нет |
{loading ? <Spinner /> : <List />} |
одно из двух |
if (!user) return <Login /> перед основным return |
большие ветки, ранний return |
объект-словарь: {icons[status]} |
много вариантов |
Ловушка: {count && <List />} при count = 0 отрисует 0. Пишите count > 0 &&.
Списки и key
<ul>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>key сообщает React, какой элемент какой между рендерами. Он должен быть уникальным среди соседей и стабильным:
| Key | Результат |
|---|---|
item.id из данных |
✓ правильно |
индекс (i) |
✗ при удалении / перестановке состояние (поля, фокус) остаётся не на той позиции |
Math.random() |
✗ каждый рендер = новый элемент, всё теряется |
Трюк: меняете key компонента → React его полностью сбрасывает.
Композиция через children
children = то, что вы кладёте между тегами компонента. Так строятся гибкие компоненты без десятков props:
function Card({ title, children }: { title: string; children: React.ReactNode }) {
return (
<section className="card">
<h2>{title}</h2>
{children}
</section>
)
}
<Card title="Профиль">
<UserBadge name="Ana" />
<button>Редактировать</button>
</Card>| Подход | Пример | Проблема |
|---|---|---|
| props-настройки | <Card showHeader showFooter footerText="..." /> |
разрастается бесконечно |
| композиция | <Card><Card.Header />...</Card> |
гибко |
Коротко
- Компонент = чистая функция, которая принимает props и возвращает JSX.
- JSX = JS с синтаксисом HTML:
className,onClick={fn},{выражения}. - Стабильный
keyиз данных в списках; композиция черезchildren.