Как работает JSX?
JSX (JavaScript XML) — это расширение синтаксиса JavaScript, которое позволяет писать структуру интерфейса в виде, напоминающем HTML, прямо внутри JavaScript-кода. JSX используется в React и React Native для описания того, как должен выглядеть пользовательский интерфейс. Несмотря на то, что выглядит как HTML, JSX — это не HTML и даже не шаблонизатор, а способ описания дерева компонентов с помощью синтаксического сахара поверх JavaScript.
Что происходит под капотом: JSX → JavaScript
JSX сам по себе не является исполняемым кодом — браузеры или интерпретаторы JavaScript (например, Node.js или Hermes в React Native) не умеют обрабатывать JSX напрямую. Прежде чем код с JSX можно будет запустить, он должен быть транспилирован (преобразован) в чистый JavaScript.
Для этого используется Babel — транспайлер, который превращает JSX в вызовы React.createElement.
Пример JSX:
const element = <Text>Hello, world!</Text>;
После транспиляции Babel преобразует этот код в:
const element = React.createElement(
Text,
null,
"Hello, world!"
);
Общая структура вызова React.createElement:
React.createElement(
type, // Тип компонента: строка ('div', 'Text') или функция/класс
props, // Свойства компонента (например, { className: 'foo' })
...children // Дочерние элементы
)
Таким образом, JSX просто предоставляет удобный способ записывать структуру компонентов.
Что можно использовать внутри JSX
1. HTML/React-компоненты
JSX позволяет использовать как встроенные компоненты (<div>, <View>, <Text>) так и пользовательские (<MyComponent />).
-
Компоненты с маленькой буквы (div, view, text) интерпретируются как HTML/нативные теги.
-
Компоненты с большой буквы (MyComponent, Header) интерпретируются как React-компоненты.
2. Выражения внутри фигурных скобок {}
Внутри JSX можно вставлять JavaScript-выражения в фигурных скобках:
const name = "Алиса";
<Text>{name}</Text> // Выведет: Алиса
Допустимые выражения:
-
переменные
-
математические выражения ({1 + 2})
-
функции ({toUpperCase(name)})
-
условные конструкции (в рамках выражений, например name && <Text>{name}</Text>)
Нельзя использовать:
- инструкции (if, for, while и т.п.)
Особенности синтаксиса JSX
1. Один корневой элемент
JSX-выражение должно иметь один корневой элемент:
Нельзя:
return (
<Text>Hello</Text>
<Text>World</Text>
);
Нужно обернуть в контейнер:
return (
<View>
<Text>Hello</Text>
<Text>World</Text>
</View>
);
Или использовать пустой React.Fragment:
return (
<>
<Text>Hello</Text>
<Text>World</Text>
</>
);
2. Атрибуты — в camelCase
JSX использует синтаксис JavaScript, а не HTML, поэтому атрибуты пишутся в стиле camelCase:
-
className вместо class
-
onPress вместо onclick
-
textAlign вместо text-align
<Text style={{ textAlign: 'center', fontSize: 18 }}>
Привет!
</Text>
3. JavaScript-объекты как значения
Если вы хотите задать объект как значение атрибута, используйте двойные фигурные скобки:
<View style={{ backgroundColor: 'red', padding: 10 }} />
Первая пара {} — интерполяция JavaScript, вторая — сам объект.
4. Компоненты могут быть функциями
JSX-компоненты можно определять как функции:
function Greeting(props) {
return <Text>Привет, {props.name}</Text>;
}
<Greeting name="Алиса" />
Такой компонент можно использовать внутри другого JSX.
5. Дети компонента
Компоненты могут принимать другие компоненты или элементы как children:
<CustomLayout>
<Text>Это содержимое внутри компонента</Text>
</CustomLayout>
Внутри CustomLayout можно обратиться к props.children.
JSX и условия
JSX не поддерживает директивы if, но можно использовать тернарный оператор:
{isLoggedIn ? <Text>Добро пожаловать</Text> : <Text>Пожалуйста, войдите</Text>}
Или логическое И:
{hasItems && <Text>У вас есть товары в корзине</Text>}
Для сложной логики можно использовать обычные функции:
function renderContent() {
if (loading) return <ActivityIndicator />;
if (error) return <Text>Ошибка</Text>;
return <Text>Данные загружены</Text>;
}
А затем вызвать в JSX:
<View>{renderContent()}</View>
JSX и списки
Списки в JSX отображаются с помощью метода map():
const items = \['Апельсин', 'Банан', 'Киви'\];
return (
<View>
{items.map((item, index) => (
<Text key={index}>{item}</Text>
))}
</View>
);
Важно: каждый элемент должен иметь уникальный key.
JSX и события
В JSX можно передавать функции на события, как в HTML, но синтаксис немного отличается:
<Button title="Нажми меня" onPress={() => alert('Нажато')} />
События пишутся с заглавной буквы (onPress, onChangeText, onSubmitEditing и др.), и передаётся функция-обработчик.
JSX и вложенность
JSX позволяет строить вложенные структуры:
<View>
<Header />
<ScrollView>
<Text>Контент</Text>
</ScrollView>
<Footer />
</View>
Каждый элемент может содержать другие элементы, что позволяет собирать интерфейс из иерархии компонентов.
JSX и функции как элементы
Можно динамически рендерить компоненты, вызывая функции, возвращающие JSX:
function renderHeader() {
return <Text style={{ fontSize: 24 }}>Заголовок</Text>;
}
<View>
{renderHeader()}
<Text>Тело</Text>
</View>
Это позволяет организовать чистый и читаемый код.
JSX в React Native
Хотя JSX в React Native используется почти так же, как в React для веба, есть особенности:
-
Вместо HTML-тегов (div, span, h1) используются нативные компоненты (View, Text, Image и т.д.).
-
Нет className, style работает не с CSS, а с JS-объектами.
-
Вся верстка построена на flexbox, а не на HTML-контейнерах.
JSX и типизация
JSX может использоваться как с обычным JavaScript, так и с TypeScript, что позволяет задавать типы пропсов компонентов, например:
type Props = {
name: string;
};
function Greeting({ name }: Props) {
return <Text>Привет, {name}</Text>;
}
Это повышает надёжность и масштабируемость кода в больших проектах.