JSX (JavaScript XML) — это синтаксическое расширение JavaScript, которое позволяет писать HTML-подобный код внутри JavaScript. JSX нужен для того, чтобы упростить создание и работу с пользовательскими интерфейсами в React и других библиотеках.
Основные причины использования JSX:
JSX — это синтаксический сахар для функции React.createElement(). Он позволяет писать HTML-подобный код прямо в JavaScript-файлах, что делает создание пользовательских интерфейсов более интуитивным и понятным.
// JSX-код
const element = <h1 className="greeting">Привет, мир!</h1>;
// То же самое в чистом JavaScript
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Привет, мир!'
);JSX был создан для решения нескольких ключевых проблем при разработке пользовательских интерфейсов:
Без JSX создание даже простых элементов становится громоздким:
// Без JSX - громоздкий синтаксис
const element = React.createElement(
'div',
{ className: 'user-card' },
React.createElement('img', {
src: user.avatar,
alt: user.name,
className: 'avatar'
}),
React.createElement('h2', null, user.name),
React.createElement('p', null, user.email),
React.createElement(
'button',
{ onClick: handleDelete },
'Удалить'
)
);// С JSX - интуитивный и понятный синтаксис
const element = (
<div className="user-card">
<img src={user.avatar} alt={user.name} className="avatar" />
<h2>{user.name}</h2>
<p>{user.email}</p>
<button onClick={handleDelete}>Удалить</button>
</div>
);JSX делает структуру компонентов визуально очевидной:
// Сложно понять структуру без JSX
function Navigation() {
return React.createElement(
'nav',
null,
React.createElement(
'ul',
null,
React.createElement('li', null,
React.createElement(Link, { to: '/' }, 'Главная')
),
React.createElement('li', null,
React.createElement(Link, { to: '/about' }, 'О нас')
),
React.createElement('li', null,
React.createElement(Link, { to: '/contact' }, 'Контакты')
)
)
);
}// С JSX структура очевидна сразу
function Navigation() {
return (
<nav>
<ul>
<li><Link to="/">Главная</Link></li>
<li><Link to="/about">О нас</Link></li>
<li><Link to="/contact">Контакты</Link></li>
</ul>
</nav>
);
}JSX позволяет легко вставлять JavaScript-выражения в HTML-подобный код:
function UserProfile({ user, isLoggedIn }) {
return (
<div className="profile">
<h1>Профиль пользователя</h1>
{isLoggedIn ? (
<div>
<img src={user.avatar} alt={user.name} />
<h2>{user.name}</h2>
<p>Возраст: {user.age}</p>
<p>Email: {user.email}</p>
<button onClick={() => sendMessage(user.id)}>
Отправить сообщение
</button>
</div>
) : (
<p>Пожалуйста, войдите в систему</p>
)}
<footer>
Создан: {new Date(user.createdAt).toLocaleDateString()}
</footer>
</div>
);
}JSX не является валидным JavaScript-кодом и должен быть транспилирован в обычные JavaScript-вызовы. Это происходит с помощью Babel или других транспайлеров.
// Исходный JSX-код
const element = (
<div className="container" id="main">
<h1>Заголовок</h1>
<p>Параграф с <strong>жирным текстом</strong></p>
</div>
);// После транспиляции Babel
const element = React.createElement(
"div",
{ className: "container", id: "main" },
React.createElement("h1", null, "Заголовок"),
React.createElement(
"p",
null,
"Параграф с ",
React.createElement("strong", null, "жирным текстом")
)
);Функция React.createElement() принимает три параметра:
// Структура React.createElement
React.createElement(
type, // 'div', 'h1', MyComponent
props, // { className: 'my-class', id: 'my-id' }
...children // дочерние элементы
)
// Примеры
React.createElement('div', { className: 'container' });
React.createElement(MyComponent, { title: 'Привет' });
React.createElement('button', { onClick: handleClick }, 'Нажми меня');JSX похож на HTML, но имеет некоторые отличия:
// Базовый синтаксис
const element = <h1>Привет, мир!</h1>;
// Атрибуты (используются camelCase)
const element = <img src="image.jpg" alt="Описание" className="photo" />;
// Самозакрывающиеся теги должны быть закрыты
const element = <br />; // правильно
// const element = <br>; // ошибка!Фигурные скобки {} позволяют вставлять JavaScript-выражения:
const name = 'Александр';
const age = 25;
const items = ['яблоко', 'банан', 'апельсин'];
function App() {
return (
<div>
{/* Вставка переменных */}
<h1>Привет, {name}!</h1>
<p>Возраст: {age}</p>
{/* Вставка выражений */}
<p>Через 5 лет вам будет {age + 5} лет</p>
{/* Вставка функций */}
<p>Случайное число: {Math.random()}</p>
{/* Вставка массивов */}
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}Некоторые атрибуты в JSX отличаются от HTML:
// Отличия от HTML
const element = (
<div>
{/* className вместо class */}
<div className="container">Контейнер</div>
{/* htmlFor вместо for */}
<label htmlFor="name">Имя:</label>
<input id="name" />
{/* onclick -> onClick (camelCase) */}
<button onClick={handleClick}>Нажми меня</button>
{/* style принимает объект */}
<div style={{
color: 'blue',
fontSize: '18px',
marginTop: '10px'
}}>
Стилизованный текст
</div>
</div>
);JSX поддерживает различные способы условного рендеринга:
function Greeting({ isLoggedIn, user }) {
return (
<div>
{/* Тернарный оператор */}
<h1>{isLoggedIn ? 'Добро пожаловать!' : 'Пожалуйста, войдите'}</h1>
{/* Логическое И */}
{isLoggedIn && <p>Привет, {user.name}!</p>}
{/* if-else с переменными */}
{(() => {
if (isLoggedIn) {
return <Dashboard user={user} />;
} else {
return <LoginForm />;
}
})()}
{/* null для скрытия элементов */}
{isLoggedIn ? <UserPanel /> : null}
</div>
);
}JSX делает код более декларативным и понятным:
// Императивный подход (без JSX)
function createTodoList(todos) {
const container = document.createElement('div');
container.className = 'todo-list';
todos.forEach(todo => {
const item = document.createElement('div');
item.className = 'todo-item';
item.textContent = todo.text;
if (todo.completed) {
item.style.textDecoration = 'line-through';
}
container.appendChild(item);
});
return container;
}// Декларативный подход (с JSX)
function TodoList({ todos }) {
return (
<div className="todo-list">
{todos.map(todo => (
<div
className="todo-item"
style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}
key={todo.id}
>
{todo.text}
</div>
))}
</div>
);
}JSX позволяет выявлять ошибки на этапе компиляции:
// Ошибки выявляются на этапе компиляции
const element = (
<div>
<h1>Заголовок</h1>
{/* Ошибка: незакрытый тег */}
<p>Параграф без закрывающего тега
{/* Ошибка: несуществующий атрибут */}
<button onClock={handleClick}>Нажми меня</button>
</div>
);JSX отлично работает с TypeScript, обеспечивая строгую типизацию:
interface User {
id: number;
name: string;
email: string;
}
interface UserCardProps {
user: User;
onDelete: (id: number) => void;
}
function UserCard({ user, onDelete }: UserCardProps) {
return (
<div className="user-card">
<h2>{user.name}</h2>
<p>{user.email}</p>
<button onClick={() => onDelete(user.id)}>Удалить</button>
</div>
);
}Компонент должен возвращать один корневой элемент:
// ❌ Ошибка: несколько корневых элементов
function BadComponent() {
return (
<h1>Заголовок</h1>
<p>Параграф</p>
);
}
// ✅ Правильно: один корневой элемент
function GoodComponent() {
return (
<div>
<h1>Заголовок</h1>
<p>Параграф</p>
</div>
);
}
// ✅ Альтернатива: React Fragment
function GoodComponent() {
return (
<>
<h1>Заголовок</h1>
<p>Параграф</p>
</>
);
}При рендеринге списков необходимо использовать уникальные ключи:
// ❌ Плохо: отсутствие ключей
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li>{todo.text}</li> // Отсутствует key
))}
</ul>
);
}
// ✅ Хорошо: уникальные ключи
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}// ❌ Ошибки
const element = (
<div class="container" onclick={handleClick}>
<input type="text" value={text}>
</div>
);
// ✅ Правильно
const element = (
<div className="container" onClick={handleClick}>
<input type="text" value={text} />
</div>
);Хотя JSX является стандартом в React, существуют альтернативы:
// Без JSX
function App() {
return React.createElement(
'div',
{ className: 'app' },
React.createElement('h1', null, 'Привет, мир!'),
React.createElement('p', null, 'Это приложение без JSX')
);
}import htm from 'htm';
import { h } from 'preact';
const html = htm.bind(h);
function App() {
return html`
<div class="app">
<h1>Привет, мир!</h1>
<p>Это приложение с HTM</p>
</div>
`;
}function h(tag, props, ...children) {
// Реализация функции h
}
function App() {
return h('div', { className: 'app' },
h('h1', null, 'Привет, мир!'),
h('p', null, 'Это приложение с template literals')
);
}JSX рекомендуется использовать в следующих случаях:
// Отлично подходит для сложных компонентов
function Dashboard({ user, stats, notifications }) {
return (
<div className="dashboard">
<header className="dashboard-header">
<h1>Панель управления</h1>
<UserMenu user={user} />
</header>
<main className="dashboard-content">
<StatsPanel stats={stats} />
<NotificationPanel notifications={notifications} />
<RecentActivity />
</main>
<footer className="dashboard-footer">
<p>© 2023 Моя компания</p>
</footer>
</div>
);
}JSX — это мощное синтаксическое расширение, которое делает разработку пользовательских интерфейсов более интуитивной и понятной:
✅ Основные преимущества:
✅ Ключевые особенности:
✅ Лучшие практики:
JSX стал стандартом в React-разработке и помогает создавать более поддерживаемый и понятный код для пользовательских интерфейсов.
Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪