JSX представляет способ описания визуального кода посредством комбинации кода на JavaScript и разметки XML.
В реальности для разработки под React использование JSX не требуется, однако примение JSX является рекомендуемым способом создания интерфейса.
JSX позволяет разработчикам писать HTML-подобный код непосредственно в JavaScript, что упрощает определение и визуализацию компонентов. По сути JSX — это своего рода надстройка для функции
React.createElement(). Это означает, что за кулисами код JSX преобразуется в простой JavaScript, который React использует для создания и управления элементами DOM.
Рассмотрим простейшее использование JSX:
const element = <h1>Hello METANIT.COM</h1>
В данном случае с помощью JSX определяется константа (компонент) element, которая представляет элемент h1, то есть заголовок с некоторым текстом:
За кулисами код компонента element преобразуется в:
const element = React.createElement("h1", null, "Hello METANIT.COM");
То есть мы можем написать и так, и так, но, визуально, использование декларативного подхода с JSX делает код более читаемым и выразительным, объединяя HTML и JavaScript в одном файле.
Теперь посмотрим, как использовать подобный код JSX и для этого определим следующую html-страницу:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" data-type="module">
// импортируем модули React 19 из ESM CDN
import React from "https://esm.sh/react@19?dev";
import ReactDOM from "https://esm.sh/react-dom@19/client?dev";
const rootNode = document.getElementById("app"); // элемент для рендеринга приложения React
// получаем корневой элемент
const root = ReactDOM.createRoot(rootNode);
const element = <h1>Hello METANIT.COM</h1> // элемент, который мы хотим создать
// рендеринг в корневой элемент
root.render(element);
</script>
</body>
</html>
Здесь мы делаем фактически все тоже самое, что и в самой первой статье. Только теперь в метод root.render() передаем компонент React, который определен с помощью JSX.
Но чтобы работать с JSX подобным образом, необходимо подключить на веб-страницу компилятор Babel, который позволяет скомпилировать приложение при запуске в браузере:
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
Также стоит отметить, что для элемента <script>, который содержит основной код приложения, определен атрибут type="text/babel". Этот атрибут и указывает, что данный код должен обрабатываться выше подключенным компилятором Babel.
Кроме того, вместо атрибута type="module", устанавливается атрибут data-type="module.
И если мы просто кинем страницу в браузер, мы увидим, как у нас отработает код JSX, а страница отобразит заголовок:
Если мы уберем подключениие скрипта компилятора Babel или уберем атрибут type="text/babel" наш код не будет работать. Более того
в браузере мы увидим ошибки, поскольку по умолчанию мы не можем определять код html в javascript, как это делается с помощью JSX. Нам обязательно
надо транслировать код JSX в обычный JavaScript, который понимается браузером. Собственно в этом и недостаток JSX - его необходимо скомпилировать в простой JavaScript с помощью таких инструментов, как Babel, что добавляет этап сборки в процесс разработки.
Однако кроме того, JSX позволяет вводить в эти элементы код JavaScript. Например, определим следующую страницу:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" data-type="module">
import React from "https://esm.sh/react@19?dev";
import ReactDOM from "https://esm.sh/react-dom@19/client?dev";
ReactDOM
.createRoot(document.getElementById("app"))
.render(
<h2>2 + 2 = {2 + 2}</h2>,
);
</script>
</body>
</html>
С помощью фигурных скобок в код html можно вводить код на JavaScript, который затем выполняется, а на веб-станице мы увидим его результат:
В выражениях можно использовать и более сложные объекты:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" data-type="module">
import React from "https://esm.sh/react@19?dev";
import ReactDOM from "https://esm.sh/react-dom@19/client?dev";
const user = {
id : 5,
age: 33,
firstName: "Tom",
lastName: "Smit",
getFullName: function(){
return `${this.firstName} ${this.lastName}`;
}
};
ReactDOM
.createRoot(document.getElementById("app"))
.render(
<div id={user.id}>
<p>Полное имя: {user.getFullName()}</p>
<p>Возраст: {user.age}</p>
<p>Время генерации данных: {new Date().toLocaleTimeString()}</p>
</div>
);
</script>
</body>
</html>
Здесь в элемент вводятся значения из объекта user, либо также мы можем использовать встроенные объекты типа Date.
Довольно часто встречается ситуация, когда нам надо создать для набора значений однотипные элементы, например, поместить все элементы из списка JavaScript в список HTML (<ul> или <щl>).
В этом случае можно использовать функцию map массива для генерации элемента HTML для каждого объекта из списка:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" data-type="module">
import React from "https://esm.sh/react@19?dev";
import ReactDOM from "https://esm.sh/react-dom@19/client?dev";
// массив данных для вывода на страницу
const langs = [ "JavaScript", "TypeScript", "Java", "C#", "Python"];
ReactDOM.createRoot(
document.getElementById("app")
)
.render(
<ul>
{langs.map((lang, index) => (
<li key={index}>{lang}</li>
))}
</ul>
);
</script>
</body>
</html>
Здесь используем функцию langs.map() для перебора всех элементов массива langs и для каждого из них генерируем элемент <li>
Если требуется применения какой-то логики, которая зависит от условий, то можно использовать тернарный оператор:
let isLoggedIn = true;
ReactDOM.createRoot(
document.getElementById("app")
)
.render(
<div>
{isLoggedIn ? <h1>Добро пожаловать</h1> : <h1>Необходимо выполнить авторизацию</h1>}
</div>
);
Здесь в зависимости от значения переменной isLoggedIn выводим соответствующий заголовок.
При работе с JSX следует учитывать ряд моментов, в частности, в JSX для установки класса применяется атрибут className, а не class.
Второй момент: атрибут style в качестве значения принимает объект javascript.
И третий момент: в JSX используется camel-case, то есть если мы хотим определить стилевое свойство для шрифта, например, свойство font-family,
то соответствующее свойство в объекте стиля будет называться fontFamily, то есть дефис отбрасывается, а следующая часть слова начинается с
заглавной буквы. Например:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
<style>
.user-info{
padding-left: 6px;
border: 1px #ccc solid;
}
</style>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" data-type="module">
import React from "https://esm.sh/react@19?dev";
import ReactDOM from "https://esm.sh/react-dom@19/client?dev";
const user = {
id : 5,
age: 33,
firstName: "Tom",
lastName: "Smit",
getFullName: function(){
return `${this.firstName} ${this.lastName}`;
}
};
const userClassName = "user-info";
const styleObj = {
color:"navy",
fontFamily:"Verdana"
};
ReactDOM
.createRoot(document.getElementById("app"))
.render(
<div className={userClassName} style={styleObj}>
<p>Полное имя: {user.getFullName()}</p>
<p>Возраст: {user.age}</p>
</div>
);
</script>
</body>
</html>
А если б мы определяли стиль inline, то это выглядело бы так:
<div className={userClassName} style={{color:"navy", fontFamily:"Verdana"}}>