Основы использования JSX в React

В этой статье мы подробно изучим как использовать JSX в React. Рассмотрим как он работает и компилируется, как встраивать в него JavaScript выражения и многое другое.
Что такое JSX и как он работает?
JSX – это специальный XML-подобный синтаксис технологии React, который позволяет нам очень просто описывать пользовательский интерфейс.
Несмотря на то, что JSX очень похож на HTML, он им не является. JSX – это расширение синтаксиса JavaScript, которое во время компиляции транслируется в обычный JavaScript.
Пример:
const element = <h1 className="title">Hello, world!</h1>;
Это код JSX. При компиляции он превратится в вызов React.createElement()
:
const element = React.createElement(
'h1',
{className: 'title'},
'Hello, world!'
);
Эти два примера идентичны и вы можете создавать React-элементы этим способом. То есть использовать JSX в React не обязательно, но в этом случае код становится более сложным и не таким наглядным. Его сложнее будет как писать, так и читать.
В процессе выполнения теги в JSX преобразуются в React-элементы. React-элементы – это то, из чего сделаны React-компоненты.
По сути, React-элементы – это простые JavaScript объекты. Если посмотреть ещё глубже, то код, приведённый выше, создаст вот такой простой объект:
const element = {
type: 'h1',
props: {
className: 'title',
children: 'Hello, world!'
}
};
Затем React использует эти объекты для создания DOM-модели и поддержания её в актуальном состоянии.
Понять, как работает JSX лучше всего на практике. Для этого создадим новое React-приложение и откроем его в редакторе VS Code.

В файле «index.js
», который является точкой входа в наше приложение, JSX синтаксис применяется в этом месте:
root.render(<App />);
При этом тег <React.StrictMode>
, предназначенный для включения строгого режима опущен.
Здесь используется тег <App />
. Когда тег начинается с заглавной буквы, то он компилируется как React-компонент. То есть:
root.render(React.createElement(App));
Когда тег начинается со строчной буквы <div>
, то он приводится к строке 'div'
, то есть к созданию HTML-элемента:
React.createElement('div')
В «index.js
» выполняется рендеринг React-компонента App
. Вместо рендеринга этого компонента мы можем написать любой другой «HTML» код:
<section>
<h2>Some title</h2>
</section>

В браузере:

Если у вас ничего не работает, то проверьте запущен ли у вас проект:
npm start
После этого, отменим все изменения, внесённые в этот файл, и перейдём в исходный код компонента App
, т.е. откроем «App.js
». В этом файле видим, что React-компонент App
– это просто функция, которая с помощью инструкции return
возвращает JSX:
function App() {
return ( ... );
}
В этом JSX присутствуют только обычные HTML-теги. При необходимости внутрь данного компонента мы можем поместить другие React-компоненты, в них третьи и так далее. Продолжать так мы можем очень долго. В этом и кроется вся основная суть React. А именно, что всё является компонентами и мы можем вкладывать их друг в друга для создания необходимого приложения.
Например, изменим содержимое return
на следующее:
import React from 'react';
import './App.css';
function App() {
return (
<header>
<h1 className="title">Заголовок</h1>
</header>
);
}
export default App;

При компиляции JSX превратится в:
function App() {
return (
React.createElement(
'header',
null,
React.createElement(
'h1',
{
className: 'title'
},
'Заголовок'
)
)
)
}
В результате мы увидим в браузере в <div>
с id="root"
заголовок <h1>
с содержимым «Заголовок». Как мы уже отмечали выше, JSX – это просто синтаксический сахар для вызова React.createElement(component, props, ...children)
. В createElement
:
component
– определяет тег создаваемого элемента;props
– набор свойств, которые нужно установить этому элементу;...children
– набор элементов через запятую, которые нужно поместить ему в качестве содержимого.
На создавать таким образом код, т.е. с помощью React.createElement()
не очень удобно, поэтому используется JSX.
Особенности JSX
1. Так как JSX – это JavaScript, то атрибут, который предназначен для установки классов, необходимо писать как className
. Т.е. так как это используется в JavaScript:
const elClassName = document.querySelector('h1').className;
Ключевое слово class
в JavaScript предназначено для создания классов.
2. В React при создании компонентов за основу принято то, что в результате мы должны возвращать один корневой элемент, включающий в себя всё остальное. Если мы попытаемся вернуть несколько корневых элементов, то получим ошибку «Adjacent JSX elements must be wrapped in an enclosing tag»:
return (
<header>
<h1 className="title">Заголовок</h1>
</header>
<main>
Содержимое
</main>
);
Таким образом чтобы исправить этот пример нам необходимо, например, всё это обернуть в какой-то другой элемент:
return (
<div className="container">
<header>
<h1 className="title">Заголовок</h1>
</header>
<main>
Содержимое
</main>
</div>
);
Также JSX позволяет возвращать массив элементов, при этом к каждому такому элементу необходимо добавить атрибут key
:
return [
<li key="A">Первый элемент списка</li>,
<li key="B">Второй элемент списка</li>,
<li key="C">Третий элемент списка</li>,
];
Встраивание выражений в JSX
Встраивание выражений в JSX осуществляется посредством фигурных скобок {...}
, внутрь которых мы можем поместить любое корректное выражение JavaScript:
const person = {
firstName: 'Alexander',
lastName: 'Maltsev',
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
const element = <p>Привет, {person.getFullName()}! React в {2 + 3} лучше с JSX.</p>;
JSX – это тоже выражение. Поэтому JSX можно использовать внутри условных конструкций, циклов, присваивать его переменным, передавать в качестве аргументов и возвращать из функций:
function greeting(userName) {
if (userName) {
return <div>Привет, {userName}!</div>;
}
return <div>Привет, гость!</div>;
}
Указание значений атрибутам
Перед тем изучить как в JSХ осуществляется задание атрибутов, сначала создадим простой React-компонент, например: Post
. Осуществляется создание компонентов в React очень просто. Первое что нужно сделать – это создать папку для этого компонента. В данном случае папку Post
в каталоге src
. В эту папку мы будем помещать все файлы, связанные с этим компонентом. Затем в этой папке создадим файл Post.js
и поместим в него следующее содержимое:
function Post(props) {
return (
<div className="post">
<h4 className="post_author">{props.author}</h4>
<div className="post_date">{props.date}</div>
<div className="post_content">{props.content}</div>
</div>
);
}
export default Post;

В этом примере props
– это параметр, посредством которого мы можем получать значения аргументов. Например, получение значение аргумента author
осуществляется посредством props.author
, date
– с помощью props.date
и так далее.
Теперь будем использовать этот компонент в App.js
:
import './App.css';
import Post from './Post/Post';
function App() {
return (
<div className="posts">
<Post author="Белякова Таисия" date="09.05.2022" content="Контент поста..." />
<Post author="Андреева Анна" date="10.05.2022" content="Контент поста..." />
<Post author="Морозов Филипп" date="11.05.2022" content="Контент поста..." />
</div>
);
}
export default App;
В JSX задание атрибутов как обычным элементам, так и React-компонентам, осуществляется подобному тому, как мы это делаем в HTML. Если значение, которое мы хотим передать является строкой, то его следует просто заключить в кавычки. Т.е. так как мы это сделали в примере, приведённом выше.
Когда мы хотим указать в качестве значения выражение JavaScript, его следует обернуть в фигурные скобки {...}
. При этом указывать кавычки не нужно:
const element = <Post author={post.author} date={post.date} content={post.content} />;
Установка детей с помощью JSX
Запись <Post />
эквивалентна <Post></Post>
. Таким образом пустые теги мы можем сразу же закрыть его с помощью />
, то есть, точно также, как в HTML:
const element = <img src={logo} className="App-logo" alt="logo" />
Теги JSX могут содержать дочерние элементы:
const element = (
<header>
<h1 className="title">Hello!</h1>
</header>
);
Передавать содержимое можно также внутрь тегов JSX, которые являются React-компонентами. Например, перепишем код в App.js
с использованием этой возможности:
import './App.css';
import Post from './Post/Post';
function App() {
return (
<div className="posts">
<Post author="Белякова Таисия" date="09.05.2022">
Контент поста...
</Post>
<Post author="Андреева Анна" date="10.05.2022">
Контент поста...
</Post>
<Post author="Морозов Филипп" date="11.05.2022">
Контент поста...
</Post>
</div>
);
}
export default App;

Получение контента переданного между открывающим и закрывающим тегами компонента осуществляется с помощью свойства children
:
function Post(props) {
return (
<div className="post">
<h4 className="post_author">{props.author}</h4>
<div className="post_date">{props.date}</div>
<div className="post_content">{props.children}</div>
</div>
);
}
export default Post;
Таким образом, у нас два способа передачи свойств компоненту: с помощью атрибутов и между тегами в качестве его содержимого.
Встроенные стили
Знать, как задавать стили с помощью атрибута style
в JSX необходимо. Но использовать этот способ в качестве основного не рекомендуется.
В большинстве случаев для стилизации элементов лучше использовать классы, определенные во внешней таблице стилей CSS. А style
использовать в React-приложениях для добавления динамически вычисляемых стилей во время рендеринга.
Задание inline стилей осуществляется с помощью атрибута style
, который принимает объект JavaScript со свойствами в стиле camelCased:
function HelloWorld() {
const divStyle = {
color: 'blue',
fontSize: '20px',
};
return <div style={divStyle}>Hello, world!</div>;
}
В этом примере мы установили для <div>
следующие стили: color: 'blue'
и font-size: '20px'
.
В JSX допускается записывать CSS свойство как строку, но делать так не желательно:
const divStyle = {
color: 'blue',
'font-size': '20px',
};
Без использования дополнительной переменной:
function HelloWorld() {
return <div style={{color: 'blue', fontSize: '20px'}}>Hello, world!</div>;
}