Можно ли использовать React без JSX? Как?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#React

Краткий ответ

Да, React можно использовать без JSX. JSX — это всего лишь синтаксический сахар для функции React.createElement(). Вся функциональность React доступна и без JSX, хотя код становится более многословным.

Основной способ использования React без JSX:

  • Использование React.createElement() напрямую

Полный ответ

JSX не является обязательным для работы с React. Это просто удобный способ записи, который компилируется в обычные вызовы React.createElement().

Пример использования React без JSX

// С JSX
const element = <div className="container">
  <h1>Привет, мир!</h1>
  <p>Это пример с JSX</p>
</div>;
 
// Без JSX (тот же результат)
const element = React.createElement(
  'div',
  { className: 'container' },
  React.createElement('h1', null, 'Привет, мир!'),
  React.createElement('p', null, 'Это пример без JSX')
);

Когда может понадобиться отказ от JSX

  1. Образовательные цели — чтобы понять, как работает React под капотом
  2. Ограничения сборки — когда нет возможности настроить транспиляцию JSX
  3. Минимизация зависимостей — для уменьшения размера бандла

Функциональные компоненты без JSX

// С JSX
function Welcome({ name }) {
  return <h1>Привет, {name}!</h1>;
}
 
// Без JSX
function Welcome({ name }) {
  return React.createElement('h1', null, 'Привет, ', name, '!');
}

Вывод: React полностью функционален без JSX, но JSX делает код более читаемым и удобным для написания.


Альтернативы JSX

1. HTM (Hyperscript Tagged Markup)

HTM — это альтернатива JSX, которая работает без транспиляции:

import htm from 'htm';
import { h } from 'preact';
 
const html = htm.bind(h);
 
// С HTM
function App() {
  return html`
    <div class="app">
      <h1>Привет, мир!</h1>
      <p>Это приложение использует HTM</p>
    </div>
  `;
}
 
// Без транспиляции!

2. Hyperscript

Библиотека для создания DOM-элементов:

import h from 'hyperscript';
 
// С hyperscript
function App() {
  return h('div.app',
    h('h1', 'Привет, мир!'),
    h('p', 'Это приложение использует hyperscript')
  );
}

3. Шаблонные строки

Самодельное решение с шаблонными строками:

function h(tag, props, ...children) {
  const element = document.createElement(tag);
  
  // Добавляем атрибуты
  if (props) {
    Object.keys(props).forEach(key => {
      if (key.startsWith('on')) {
        // Обработчики событий
        element.addEventListener(
          key.slice(2).toLowerCase(), 
          props[key]
        );
      } else {
        // Атрибуты
        element.setAttribute(
          key === 'className' ? 'class' : key, 
          props[key]
        );
      }
    });
  }
  
  // Добавляем дочерние элементы
  children.flat().forEach(child => {
    if (typeof child === 'string') {
      element.appendChild(document.createTextNode(child));
    } else {
      element.appendChild(child);
    }
  });
  
  return element;
}
 
// Использование
function App() {
  return h('div', { className: 'app' },
    h('h1', null, 'Привет, мир!'),
    h('p', null, 'Это приложение использует шаблонные строки')
  );
}

Преимущества использования React без JSX

1. Меньше зависимостей

Отказ от JSX уменьшает количество зависимостей:

// С JSX требуется Babel и пресеты
// package.json
{
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/preset-react": "^7.0.0"
  }
}
 
// Без JSX можно обойтись меньшим количеством зависимостей
// package.json
{
  "dependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}

2. Более быстрая сборка

Без транспиляции JSX сборка может быть быстрее:

// webpack.config.js для проекта без JSX
module.exports = {
  // Нет необходимости в babel-loader для JSX
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'] // Только JavaScript
            // Нет необходимости в '@babel/preset-react'
          }
        }
      }
    ]
  }
};

3. Понимание внутренней работы

Использование React без JSX помогает понять, как работает библиотека:

// Видно, что происходит на самом деле
const element = React.createElement(
  'div',
  { className: 'container' },
  React.createElement('h1', null, 'Заголовок'),
  React.createElement('p', null, 'Параграф')
);
 
// Это преобразуется в объект вроде:
/*
{
  type: 'div',
  props: {
    className: 'container',
    children: [
      {
        type: 'h1',
        props: {
          children: 'Заголовок'
        }
      },
      {
        type: 'p',
        props: {
          children: 'Параграф'
        }
      }
    ]
  }
}
*/

Недостатки использования React без JSX

1. Многословность кода

Код без JSX становится значительно длиннее:

// С JSX - компактно и понятно
function Navigation() {
  return (
    <nav>
      <ul>
        <li><a href="/">Главная</a></li>
        <li><a href="/about">О нас</a></li>
        <li><a href="/contact">Контакты</a></li>
      </ul>
    </nav>
  );
}
 
// Без JSX - многословно и сложно читать
function Navigation() {
  return React.createElement(
    'nav',
    null,
    React.createElement(
      'ul',
      null,
      React.createElement('li', null, 
        React.createElement('a', { href: '/' }, 'Главная')
      ),
      React.createElement('li', null, 
        React.createElement('a', { href: '/about' }, 'О нас')
      ),
      React.createElement('li', null, 
        React.createElement('a', { href: '/contact' }, 'Контакты')
      )
    )
  );
}

2. Сложность вложения

Сложные вложенные структуры становятся трудными для понимания:

// С JSX - структура очевидна
function Dashboard() {
  return (
    <div className="dashboard">
      <header>
        <h1>Панель управления</h1>
        <nav>
          <ul>
            <li><a href="#profile">Профиль</a></li>
            <li><a href="#settings">Настройки</a></li>
          </ul>
        </nav>
      </header>
      <main>
        <section>
          <h2>Статистика</h2>
          <div className="charts">
            <div className="chart">График 1</div>
            <div className="chart">График 2</div>
          </div>
        </section>
      </main>
    </div>
  );
}
 
// Без JSX - сложно понять структуру
function Dashboard() {
  return React.createElement(
    'div',
    { className: 'dashboard' },
    React.createElement(
      'header',
      null,
      React.createElement('h1', null, 'Панель управления'),
      React.createElement(
        'nav',
        null,
        React.createElement(
          'ul',
          null,
          React.createElement('li', null,
            React.createElement('a', { href: '#profile' }, 'Профиль')
          ),
          React.createElement('li', null,
            React.createElement('a', { href: '#settings' }, 'Настройки')
          )
        )
      )
    ),
    React.createElement(
      'main',
      null,
      React.createElement(
        'section',
        null,
        React.createElement('h2', null, 'Статистика'),
        React.createElement(
          'div',
          { className: 'charts' },
          React.createElement('div', { className: 'chart' }, 'График 1'),
          React.createElement('div', { className: 'chart' }, 'График 2')
        )
      )
    )
  );
}

3. Отсутствие статической проверки

Без JSX теряется часть статической проверки ошибок:

// С JSX - ошибки выявляются на этапе компиляции
// <div class="container">  // Ошибка: должно быть className
//   <p>Параграф</p>
//   <!-- Незакрытый тег -->  // Ошибка: незакрытый тег
// </div>
 
// Без JSX - ошибки могут остаться незамеченными
const element = React.createElement(
  'div',
  { class: 'container' },  // Ошибка не выявляется сразу
  React.createElement('p', null, 'Параграф')
  // Пропущен закрывающий элемент
);

Когда использовать React без JSX

1. Образовательные цели

Для понимания внутренней работы React:

// Отличный способ понять, как работает Virtual DOM
function createElementDemo() {
  const element = React.createElement(
    'button',
    { 
      onClick: () => console.log('Кнопка нажата'),
      style: { backgroundColor: 'blue', color: 'white' }
    },
    'Нажми меня'
  );
  
  console.log(element); // Видим структуру Virtual DOM
  
  return element;
}

2. Минималистичные проекты

Когда нужно минимальное количество зависимостей:

// Минимальный React-приложение без JSX
import { createRoot } from 'react-dom/client';
 
function App() {
  return React.createElement(
    'div',
    null,
    React.createElement('h1', null, 'Минимальное приложение'),
    React.createElement('p', null, 'Без JSX и дополнительных зависимостей')
  );
}
 
const root = createRoot(document.getElementById('root'));
root.render(React.createElement(App));

3. Специфические среды выполнения

В средах, где нет возможности настроить транспиляцию:

// В браузерной консоли или CodePen без Babel
// Можно использовать React напрямую
const element = React.createElement(
  'div',
  { style: { textAlign: 'center' } },
  React.createElement('h1', null, 'Привет из консоли!'),
  React.createElement('p', null, 'React без JSX')
);
 
ReactDOM.render(element, document.getElementById('app'));

Практические рекомендации

1. Использование вспомогательных функций

Для упрощения кода можно создать вспомогательные функции:

// Вспомогательная функция для создания элементов
function h(type, props, ...children) {
  return React.createElement(type, props, ...children);
}
 
// Упрощает написание кода
function App() {
  return h('div', { className: 'app' },
    h('h1', null, 'Заголовок'),
    h('p', null, 'Параграф'),
    h('button', { onClick: handleClick }, 'Кнопка')
  );
}

2. Использование объектов для props

Для улучшения читаемости можно использовать объекты:

// Вместо длинных списков параметров
const buttonProps = {
  className: 'btn btn-primary',
  onClick: handleClick,
  disabled: isLoading,
  style: { marginTop: '10px' }
};
 
const element = React.createElement(
  'button',
  buttonProps,
  isLoading ? 'Загрузка...' : 'Отправить'
);

3. Создание фабричных функций

Для часто используемых элементов:

// Фабричные функции для часто используемых элементов
const div = (props, ...children) => React.createElement('div', props, ...children);
const button = (props, ...children) => React.createElement('button', props, ...children);
const input = (props) => React.createElement('input', props);
 
// Упрощает использование
function Form() {
  return div({ className: 'form' },
    input({ type: 'text', placeholder: 'Имя' }),
    input({ type: 'email', placeholder: 'Email' }),
    button({ onClick: handleSubmit }, 'Отправить')
  );
}

Резюме

React можно использовать без JSX, и это может быть полезно в определенных ситуациях:

Когда это уместно:

  • Образовательные цели — для понимания внутренней работы
  • Минималистичные проекты — для уменьшения зависимостей
  • Специфические среды — где нет транспиляции
  • Эксперименты — для тестирования подходов

Когда лучше использовать JSX:

  • Производственные приложения — для читаемости и поддержки
  • Командная разработка — для единообразия кода
  • Сложные интерфейсы — для упрощения разработки

Ключевые моменты:

  • JSX — это синтаксический сахар для React.createElement()
  • Всю функциональность React можно использовать без JSX
  • Код без JSX более многословный, но работает так же
  • Альтернативы JSX (htm, hyperscript) могут быть полезны

Понимание возможности использования React без JSX помогает глубже понять библиотеку и принимать более обоснованные решения при выборе инструментов для проекта.


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪