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

Основы использования JSX в React
Содержание:
  1. Что такое JSX и как он работает?
  2. Особенности JSX
  3. Встраивание выражений в JSX
  4. Указание значений атрибутам
  5. Установка детей с помощью JSX
  6. Встроенные стили
  7. Комментарии

В этой статье мы подробно изучим как использовать 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, который является точкой входа в наше React-приложение

В файле «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>
Вместо компонента App мы выполняем рендеринг другого кода

В браузере:

Вид React-приложения в браузере

Если у вас ничего не работает, то проверьте запущен ли у вас проект:

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;
Содержимое React-компонента 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;
Создание простого React-компонента App

В этом примере 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;
Передача содержимого внутрь тегов JSX

Получение контента переданного между открывающим и закрывающим тегами компонента осуществляется с помощью свойства 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>;
}

Комментарии: 2

euphoria
euphoria

Пару ошибок нашлось:

  • Перед разделом "Особенности JSX", должно быть "На" вместо "Но"
  • В разделе "Указание значений атрибутам", должно быть "перед тем как" вместо "перед тем"
  • В разделе "Установка детей с помощью JSX" , во втором предложении лишнее слово "его"
Александр Мальцев
Александр Мальцев

Спасибо, поправил.