← React/Что такое React и зачем он нужен#256 из 383← ПредыдущийСледующий →+15 XP
Полезно по теме:Гайд: React или VueПрактика: React setТермин: React HooksТема: React: хуки и экосистема

Что такое React и зачем он нужен

React — это библиотека, а не фреймворк

React — это JavaScript-библиотека для построения пользовательских интерфейсов, созданная и поддерживаемая Facebook (Meta). В отличие от Vue или Angular, React — именно библиотека: она отвечает только за UI-слой, а маршрутизацию, управление состоянием и другие задачи вы решаете дополнительными пакетами по своему выбору.

Это ключевое отличие: React даёт больше свободы, но требует больше решений от разработчика.

Проблема, которую решает React

До React (и jQuery-эпохи) обновление интерфейса выглядело так:

// Ручное управление DOM — императивный подход
let count = 0
const display = document.getElementById('count')
const button = document.getElementById('btn')

button.addEventListener('click', () => {
  count++
  display.textContent = count  // вручную синхронизируем UI с данными

  // При сложных UI это превращается в хаос:
  // нужно помнить о КАЖДОМ элементе, который зависит от count
  document.getElementById('badge').textContent = count
  document.getElementById('title').textContent = `Счётчик: ${count}`
  if (count > 10) {
    document.getElementById('warning').style.display = 'block'
  }
})

React предлагает декларативный подход: вы описываете КАК выглядит UI для данного состояния, а React сам решает что изменить в DOM:

// React — декларативный подход
function Counter() {
  const [count, setCount] = React.useState(0)

  return (
    <div>
      <p>{count}</p>
      <span className="badge">{count}</span>
      <h1>Счётчик: {count}</h1>
      {count > 10 && <p className="warning">Слишком много!</p>}
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

Вы описываете "что отображать", а не "как обновлять". React сам эффективно обновит только изменившиеся части DOM.

Виртуальный DOM

React поддерживает виртуальный DOM (Virtual DOM) — облегчённое JavaScript-представление реального DOM. Алгоритм работы:

1. При изменении состояния React строит новое виртуальное дерево

2. Сравнивает его со старым виртуальным деревом (алгоритм diffing)

3. Вычисляет минимальный набор изменений (reconciliation)

4. Применяет только эти изменения к реальному DOM (batching)

Прямые операции с реальным DOM дорогостоящие — виртуальный DOM позволяет минимизировать их количество.

React vs Vue vs Angular

| Критерий | React | Vue 3 | Angular |

|---|---|---|---|

| Тип | Библиотека | Прогрессивный фреймворк | Полный фреймворк |

| Язык | JSX + JS/TS | SFC (.vue) + JS/TS | TypeScript (обязательно) |

| Экосистема | Свободный выбор | Частично включена | Всё включено |

| Порог входа | Средний | Низкий | Высокий |

| Размер | ~45kb | ~30kb | ~150kb+ |

| Использование | Meta, Netflix, Airbnb | Alibaba, Xiaomi | Google, enterprise |

Вы уже знаете Vue 3 — React будет понятен: те же концепции компонентов и реактивности, просто другой синтаксис и философия.

Настройка проекта

Современный способ создать React-проект — Vite (он же рекомендован для Vue):

# Создать новый React + TypeScript проект
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev

Также популярен Next.js — React-фреймворк с SSR, файловым роутингом и многим другим (для продакшн-приложений):

npx create-next-app@latest my-app --typescript

Компонентная архитектура

React-приложение — это дерево компонентов. Каждый компонент — это функция, которая принимает данные (props) и возвращает описание UI (JSX):

// App.jsx — корневой компонент
function App() {
  return (
    <div>
      <Header />          // дочерний компонент
      <main>
        <ProductList />   // компонент-контейнер
      </main>
      <Footer />
    </div>
  )
}

Компоненты — строительные блоки. Каждый инкапсулирует собственную логику, состояние и отображение.

Примеры

Сравнение императивного (jQuery-стиль) и декларативного (React-стиль) подходов: счётчик двумя способами

// ============================================================
// ИМПЕРАТИВНЫЙ ПОДХОД (jQuery / vanilla JS)
// Вручную управляем каждым элементом DOM
// ============================================================

function createImperativeCounter(container) {
  let count = 0
  let domOperations = 0  // считаем обращения к DOM

  // Создаём DOM-элементы вручную
  const wrapper = document.createElement('div')
  const display = document.createElement('h2')
  const badge = document.createElement('span')
  const btn = document.createElement('button')

  display.textContent = `Счётчик: ${count}`
  badge.textContent = count
  btn.textContent = '+1'

  wrapper.append(display, badge, btn)
  domOperations += 3  // три операции создания

  btn.addEventListener('click', () => {
    count++
    // Обновляем КАЖДЫЙ элемент вручную
    display.textContent = `Счётчик: ${count}`  // DOM операция 1
    badge.textContent = count                    // DOM операция 2
    domOperations += 2
    console.log(`[Императивно] Клик #${count}, DOM операций всего: ${domOperations}`)
  })

  return wrapper
}

// ============================================================
// ДЕКЛАРАТИВНЫЙ ПОДХОД (имитация React)
// Описываем желаемое состояние — рантайм решает что обновить
// ============================================================

function createDeclarativeCounter() {
  let count = 0
  let domOperations = 0

  // "Рендер-функция" описывает весь UI как HTML-строку
  function render(state) {
    return `
      <div>
        <h2>Счётчик: ${state.count}</h2>
        <span>${state.count}</span>
        <button id="dec-btn">+1</button>
      </div>
    `
  }

  // Простая реализация "diffing": заменяем только изменившееся
  let prevHTML = ''
  function update(container) {
    const newHTML = render({ count })
    if (newHTML !== prevHTML) {
      container.innerHTML = newHTML  // 1 DOM операция на любое изменение!
      domOperations++
      prevHTML = newHTML
      // Переподключаем обработчик после перерисовки
      container.querySelector('#dec-btn').addEventListener('click', handleClick)
    }
  }

  function handleClick() {
    count++
    console.log(`[Декларативно] Клик #${count}, DOM операций всего: ${domOperations + 1}`)
    update(document.getElementById('decl-root'))
  }

  return { render: update, initialHTML: render({ count: 0 }) }
}

// --- Вывод в консоль для демонстрации ---
console.log('Императивный подход: при каждом клике обновляем N элементов вручную')
console.log('Декларативный подход: описываем результат, рантайм минимизирует DOM-операции')
console.log('')
console.log('React делает именно это — только намного умнее:')
console.log('вместо innerHTML он точечно обновляет изменившиеся узлы через Virtual DOM')

// React эквивалент (для справки):
// function Counter() {
//   const [count, setCount] = React.useState(0)
//   return (
//     <div>
//       <h2>Счётчик: {count}</h2>
//       <span>{count}</span>
//       <button onClick={() => setCount(count + 1)}>+1</button>
//     </div>
//   )
// }

Что такое React и зачем он нужен

React — это библиотека, а не фреймворк

React — это JavaScript-библиотека для построения пользовательских интерфейсов, созданная и поддерживаемая Facebook (Meta). В отличие от Vue или Angular, React — именно библиотека: она отвечает только за UI-слой, а маршрутизацию, управление состоянием и другие задачи вы решаете дополнительными пакетами по своему выбору.

Это ключевое отличие: React даёт больше свободы, но требует больше решений от разработчика.

Проблема, которую решает React

До React (и jQuery-эпохи) обновление интерфейса выглядело так:

// Ручное управление DOM — императивный подход
let count = 0
const display = document.getElementById('count')
const button = document.getElementById('btn')

button.addEventListener('click', () => {
  count++
  display.textContent = count  // вручную синхронизируем UI с данными

  // При сложных UI это превращается в хаос:
  // нужно помнить о КАЖДОМ элементе, который зависит от count
  document.getElementById('badge').textContent = count
  document.getElementById('title').textContent = `Счётчик: ${count}`
  if (count > 10) {
    document.getElementById('warning').style.display = 'block'
  }
})

React предлагает декларативный подход: вы описываете КАК выглядит UI для данного состояния, а React сам решает что изменить в DOM:

// React — декларативный подход
function Counter() {
  const [count, setCount] = React.useState(0)

  return (
    <div>
      <p>{count}</p>
      <span className="badge">{count}</span>
      <h1>Счётчик: {count}</h1>
      {count > 10 && <p className="warning">Слишком много!</p>}
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

Вы описываете "что отображать", а не "как обновлять". React сам эффективно обновит только изменившиеся части DOM.

Виртуальный DOM

React поддерживает виртуальный DOM (Virtual DOM) — облегчённое JavaScript-представление реального DOM. Алгоритм работы:

1. При изменении состояния React строит новое виртуальное дерево

2. Сравнивает его со старым виртуальным деревом (алгоритм diffing)

3. Вычисляет минимальный набор изменений (reconciliation)

4. Применяет только эти изменения к реальному DOM (batching)

Прямые операции с реальным DOM дорогостоящие — виртуальный DOM позволяет минимизировать их количество.

React vs Vue vs Angular

| Критерий | React | Vue 3 | Angular |

|---|---|---|---|

| Тип | Библиотека | Прогрессивный фреймворк | Полный фреймворк |

| Язык | JSX + JS/TS | SFC (.vue) + JS/TS | TypeScript (обязательно) |

| Экосистема | Свободный выбор | Частично включена | Всё включено |

| Порог входа | Средний | Низкий | Высокий |

| Размер | ~45kb | ~30kb | ~150kb+ |

| Использование | Meta, Netflix, Airbnb | Alibaba, Xiaomi | Google, enterprise |

Вы уже знаете Vue 3 — React будет понятен: те же концепции компонентов и реактивности, просто другой синтаксис и философия.

Настройка проекта

Современный способ создать React-проект — Vite (он же рекомендован для Vue):

# Создать новый React + TypeScript проект
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev

Также популярен Next.js — React-фреймворк с SSR, файловым роутингом и многим другим (для продакшн-приложений):

npx create-next-app@latest my-app --typescript

Компонентная архитектура

React-приложение — это дерево компонентов. Каждый компонент — это функция, которая принимает данные (props) и возвращает описание UI (JSX):

// App.jsx — корневой компонент
function App() {
  return (
    <div>
      <Header />          // дочерний компонент
      <main>
        <ProductList />   // компонент-контейнер
      </main>
      <Footer />
    </div>
  )
}

Компоненты — строительные блоки. Каждый инкапсулирует собственную логику, состояние и отображение.

Примеры

Сравнение императивного (jQuery-стиль) и декларативного (React-стиль) подходов: счётчик двумя способами

// ============================================================
// ИМПЕРАТИВНЫЙ ПОДХОД (jQuery / vanilla JS)
// Вручную управляем каждым элементом DOM
// ============================================================

function createImperativeCounter(container) {
  let count = 0
  let domOperations = 0  // считаем обращения к DOM

  // Создаём DOM-элементы вручную
  const wrapper = document.createElement('div')
  const display = document.createElement('h2')
  const badge = document.createElement('span')
  const btn = document.createElement('button')

  display.textContent = `Счётчик: ${count}`
  badge.textContent = count
  btn.textContent = '+1'

  wrapper.append(display, badge, btn)
  domOperations += 3  // три операции создания

  btn.addEventListener('click', () => {
    count++
    // Обновляем КАЖДЫЙ элемент вручную
    display.textContent = `Счётчик: ${count}`  // DOM операция 1
    badge.textContent = count                    // DOM операция 2
    domOperations += 2
    console.log(`[Императивно] Клик #${count}, DOM операций всего: ${domOperations}`)
  })

  return wrapper
}

// ============================================================
// ДЕКЛАРАТИВНЫЙ ПОДХОД (имитация React)
// Описываем желаемое состояние — рантайм решает что обновить
// ============================================================

function createDeclarativeCounter() {
  let count = 0
  let domOperations = 0

  // "Рендер-функция" описывает весь UI как HTML-строку
  function render(state) {
    return `
      <div>
        <h2>Счётчик: ${state.count}</h2>
        <span>${state.count}</span>
        <button id="dec-btn">+1</button>
      </div>
    `
  }

  // Простая реализация "diffing": заменяем только изменившееся
  let prevHTML = ''
  function update(container) {
    const newHTML = render({ count })
    if (newHTML !== prevHTML) {
      container.innerHTML = newHTML  // 1 DOM операция на любое изменение!
      domOperations++
      prevHTML = newHTML
      // Переподключаем обработчик после перерисовки
      container.querySelector('#dec-btn').addEventListener('click', handleClick)
    }
  }

  function handleClick() {
    count++
    console.log(`[Декларативно] Клик #${count}, DOM операций всего: ${domOperations + 1}`)
    update(document.getElementById('decl-root'))
  }

  return { render: update, initialHTML: render({ count: 0 }) }
}

// --- Вывод в консоль для демонстрации ---
console.log('Императивный подход: при каждом клике обновляем N элементов вручную')
console.log('Декларативный подход: описываем результат, рантайм минимизирует DOM-операции')
console.log('')
console.log('React делает именно это — только намного умнее:')
console.log('вместо innerHTML он точечно обновляет изменившиеся узлы через Virtual DOM')

// React эквивалент (для справки):
// function Counter() {
//   const [count, setCount] = React.useState(0)
//   return (
//     <div>
//       <h2>Счётчик: {count}</h2>
//       <span>{count}</span>
//       <button onClick={() => setCount(count + 1)}>+1</button>
//     </div>
//   )
// }

Задание

Создай компонент App, который отображает приветственное сообщение и описание React. Компонент должен показывать: заголовок h1 с текстом "Привет, React!", абзац p с объяснением что React — это декларативная библиотека для UI, и стилизованный блок div с классом-подсказкой о виртуальном DOM.

Подсказка

Присвой переменной title строку "Привет, React!". В JSX вставляй переменные через фигурные скобки: {title}, {description}. Компонент App должен возвращать JSX-разметку с div-обёрткой.

Загружаем среду выполнения...
Загружаем AI-помощника...