Глава 10 Альтернативы React

Будущее React

Книга
React. К вершинам мастерства

Fluent React: Build Fast, Performant, and Intuitive Web Applications

Глубокое погружение во внутреннее устройство React: JSX и продвинутые паттерны, виртуальный DOM и реконциляция, серверный рендеринг, конкурентный режим и серверные компоненты.

Глава 10 · Финал

Примет ли React сигналы?

Реактивные примитивы вроде сигналов разошлись по всей интерфейсной экосистеме — логично предположить, что React в конечном итоге примет аналогичный «сигнальный» подход. Однако команда React заявила, что «не в восторге» от сигналов, и выбирает альтернативную технологию, чтобы добиться тех же преимуществ в производительности, которые обеспечивают сигналы.

  • Сначала подытожим на примере, как React обновляет интерфейс — и где он теряет производительность.
  • Посмотрим на ручное решение через memo и на его цену.
  • Разберём философию команды React: почему сигналы для них — деталь реализации.
  • Познакомимся с React Forget — компилятором, который должен решить задачу за нас.
  • И честно взвесим Forget против сигналов — вместе со скепсисом автора книги.
Шаг 1 · Где React теряет производительность

Грубая реактивность на очень замысловатом примере

Counter.jsxповедение по умолчанию
import React, { useState } from "react";
import { ComponentWithExpensiveChildren }
  from "./ExpensiveComponent";

function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>Increment</button>
      <ComponentWithExpensiveChildren />
    </div>
  );
}
  • В компоненте три дочерних элемента: <p> со значением счётчика, <button>, который его увеличивает, и <ComponentWithExpensiveChildren> — он отображает дорогостоящие дочерние элементы с большим количеством вычислений.
  • Нажимаем кнопку. Функция Counter вызывается заново — вместе со всеми её дочерними элементами. Это поведение React по умолчанию.
  • Значит, ComponentWithExpensiveChildren отрисовывается повторно, хотя в этом нет необходимости: его пропсы и состояние не изменились.
Такая грубая реактивность делает React менее производительным, чем он мог бы быть.
Шаг 2 · Ручное решение

memo работает — пока мы про него помним

Исправить это довольно легко: включаем memo в нужное время и в нужном месте.

Counter.jsxс мемоизацией
import React, { useState, memo } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <MemoizedComponentWithExpensiveChildren />
    </div>
  );
}

const MemoizedComponentWithExpensiveChildren = memo(
  ComponentWithExpensiveChildren
);

Что получилось

В этом случае обеспечивается такая же детализированная реактивность, как при использовании сигналов: дорогим поддеревом React больше не занимается, пока его пропсы не изменились.

Чего это стоит

Это работает до тех пор, пока мы не забываем использовать memo везде, где нам нужно. И потому это не так удобно, как сигналы: мемоизация — обязанность разработчика, а не свойство модели.

Шаг 3 · Почему не сигналы

Философия команды React

Многим кажется, что сигналы легко решили бы эту проблему. Но команда React в Meta считает, что сигналы, как и memo, могут быть деталями реализации, о которых обычным разработчикам задумываться не следует. Они прислушиваются к первоначальному ценностному предложению React.

«Описывайте свой пользовательский интерфейс декларативно и дайте React сделать всё остальное».

Лучший способ — когда думать не надо

Команда React считает, что лучший способ — это когда разработчики не заботятся о сигналах, memo или каких-либо деталях, а фреймворк должен быть в состоянии сам найти оптимальный способ визуализации интерфейса.

Значит, задачу решает инструмент

С этой целью команда работает над новым программным обеспечением, предназначенным именно для этого. Речь идёт о React Forget.

Шаг 4 · React Forget

Линтер с включённым флагом --fix

Forget — это набор инструментов для React, похожий на линтер с включённым --fix. Он применяет правила React, а затем автоматически преобразует код React в оптимальный, интеллектуально запоминая значения, которые не будут меняться на протяжении жизненного цикла приложения — такие как ComponentWithExpensiveChildren.

Подход похож на тот, что использует Svelte — но Svelte компилирует в императивный код, а Forget компилирует в более производительный React. Виртуальный DOM и согласование остаются на месте.

Именно благодаря правилам компилятор может предсказать неизменные значения и сохранить их в памяти за нас. Каковы эти правила?

  • Компоненты React предполагаются чистыми функциями; некоторые хуки и пользовательские обработчики событий чистыми быть не обязаны.
  • Запрещено: изменять переменные и объекты, которые не были созданы в функции заново; читать свойства, которые могут измениться.
  • Разрешено: читать свойства или состояние; генерировать ошибки; мутировать вновь созданные объекты и привязки.
  • Исключение: отложенная (ленивая) инициализация — здесь мутация с целью инициализации допускается.
  • Объекты и замыкания, созданные во время рендеринга, не должны изменяться после его завершения — кроме изменяемых объектов, сохранённых в состоянии.
Шаг 5 · Честный скепсис автора

Forget против сигналов

На момент написания книги Forget был закрытым: он проходил оценку в Meta и превосходил ожидания по использованию в Instagram и WhatsApp, а команда рассматривала возможность выпустить его как open source. Судить о компромиссах авторитетно было сложно — но предположить можно.

Почему сигналы всё равно могут выигрывать

Даже если Forget запомнит всё, что не меняется, сигналы живут в параллельной вселенной за пределами иерархии компонентов. Поэтому при обновлении React всё равно придётся пройти по всему дереву компонентов и сравнить старые и новые пропсы каждого, чтобы определить, кто нуждается в повторном рендеринге.

Как это происходит у «сигнальных»

В сигнальных фреймворках обновляются только реагирующие части интерфейса — без необходимости обхода дерева. Отсюда предварительный вывод: даже с компилятором Forget React всё ещё может работать медленнее библиотек, где сигналы используются по умолчанию.

Заключение книги дословно: «...но пока рано говорить об этом».
Август 2026 · Сверяем часы

Forget вырос в React Compiler

Это тот раздел книги, где проверка временем самая интересная: почти всё, что было «в оценке в Meta», уже случилось.

Что обещала книгаЧто произошло
сбылось Возможный выпуск Forget в open source «в ближайшем будущем»Forget вышел под именем React Compiler: бета — октябрь 2024, стабильная v1.0 — 7 октября 2025 (React Conf). Открыт, обкатан на приложениях Meta, работает и в React, и в React Native
сбылось «Правила React» как условие работы компилятораПравила стали проверяемыми: они въехали в eslint-plugin-react-hooks вместе с правилами самого компилятора. Ручные useMemo, useCallback и memo компилятор сохраняет — «раз вы их написали, значит, была причина»
сбылось Разработчик не должен думать о memoКомпилятор мемоизирует по анализу и эвристикам, в большинстве случаев не хуже, чем сделал бы человек. Для нового кода рекомендуется полагаться на компилятор, а useMemo/useCallback оставить как escape hatch для точного контроля
сбылось React не пойдёт по пути сигналовТак и есть: TC39 proposal-signals — Stage 1, за ним Angular, Vue, Solid, Preact, Ember, Qwik, MobX. React выбрал компилятор и остался при vDOM
частично «Даже с Forget React может быть медленнее сигнальных»Скепсис не опровергнут: модель осталась pull-based, обход дерева и сравнение пропсов никуда не ушли. Компилятор снял издержки ручной мемоизации, а не архитектурную разницу
Будущее, о котором книга ещё не знала

Куда React пошёл, кроме компилятора

Книга закрылась на Forget. За два года «будущее React» оказалось шире одного компилятора — и всё в том же направлении: не менять модель реактивности, а сокращать её издержки.

КОНЕЦ 2024

React 19

Серверные компоненты и server actions — в стабильном ядре. Работа переносится на сервер: клиенту едет меньше JavaScript. Это глава 9, которую мы уже разобрали.

ОКТЯБРЬ 2025

React 19.2

<Activity mode> — участки UI как видимые, скрытые или приостановленные; useEffectEvent — событийная логика отдельно от реактивных эффектов; cacheSignal; частичный пререндеринг; улучшенный трекинг производительности.

МАЙ 2026

React 19.2.6

Текущий стабильный релиз. React Compiler поддерживает 19.2 стабильно — компилятор и рантайм наконец идут в одном такте.

Общая линия: модель не меняется, меняется цена её работы — компилятор убирает ручную мемоизацию, конкурентный рендеринг расставляет приоритеты, серверные компоненты уносят работу с клиента.
Проверьте ваши знания

Пять вопросов главы 10

Вопросы из книги — по всей главе. Сначала обсуждаем, потом клик по вопросу раскрывает тезисный ответ.

Чем отличается модель реактивности в React, Vue, Svelte, Solid и Angular? Как это влияет на производительность и опыт разработки?

React — явный сеттер и повторный запуск функции компонента, дальше diff виртуального DOM (крупнозернисто). Vue — реактивные объекты плюс vDOM. Svelte — зависимости размечает компилятор, на выходе императивный код, обновляющий DOM напрямую. Solid — сигналы, компонент выполняется один раз, обновляются только читавшие узлы. Angular — обнаружение изменений в зонах и наблюдаемые объекты. Производительность: мелкозернистые модели не обходят дерево, React платит обходом и сравнением. Опыт разработки: React даёт предсказуемость и атомарность обновлений, сигнальные — меньше ручной оптимизации.

Опишите уникальный подход Qwik к максимизации производительности. Чем он отличается от остальных?

Возобновляемость вместо гидратации: состояние приложения сериализуется в HTML, и браузер продолжает работу с того места, где остановился сервер, вместо повторного выполнения кода на клиенте. Плюс приоритетная загрузка: JavaScript подтягивается по мере необходимости — по взаимодействию. Остальные платформы сначала гидратируют дерево целиком.

Каковы сильные и слабые стороны каждой библиотеки из главы? Как это влияет на выбор под конкретный проект?

Vue — мягкая кривая обучения и ненавязчивая реактивность; Angular — цельный «всё в комплекте» фреймворк с высокой ценой входа; Svelte — минимум рантайма, свой язык; Solid — самая точная реактивность при JSX-синтаксисе; Qwik — лучший первый экран, но самая молодая экосистема (это единственный недостаток, который книга называет прямо). React — крупнозернистая модель, зато крупнейшая экосистема и найм. Выбор — про команду, экосистему и профиль нагрузки, а не про «кто быстрее в бенчмарке».

React не является реактивным в традиционном смысле. Объясните это, сравнив с push-моделью Vue или Svelte.

В push-модели запись значения сама уведомляет подписчиков — изменение распространяется по системе. React работает pull: сеттер лишь планирует рендер, дальше функция компонента выполняется заново целиком и React сравнивает результат с прежним деревом. Формула v = f(s) это и фиксирует: представление есть функция состояния, но обновляется не само, а при повторном выполнении функции.

Что такое React Forget? Как он работает и как соотносится с сигналами?

Набор инструментов, похожий на линтер с --fix: применяет правила React и автоматически мемоизирует значения, которые не меняются за жизнь приложения, — компилируя React в более производительный React (в отличие от Svelte, компилирующего в императивный код). С сигналами не конкурирует по механике: сигналы живут вне иерархии компонентов и не требуют обхода дерева, а React обход сохраняет. Сегодня это React Compiler v1.0 — стабилен с октября 2025.

Обзор главы · Посадим наш самолёт

Глава 10 — в пяти строках

Этот доклад закрывает главу об альтернативах. Дальше — заключительная глава, где книга собирает всю картину целиком.

  • Пять альтернатив по отдельности: Vue, Angular, Svelte, Solid и Qwik — каждая со своей философией, своими реактивными примитивами и своими компромиссами.
  • Общие шаблоны: компонентная архитектура, декларативный синтаксис, механизм обновлений, методы жизненного цикла и современный JS-инструментарий — у всех.
  • React не реактивен в традиционном смысле: грубый подход «изменение состояния → повторный рендеринг» вместо детализированной модели Vue и Svelte.
  • Будущее React — не сигналы, а компилятор: Forget автоматически оптимизирует код, запоминая неизменные значения; сегодня это стабильный React Compiler.
  • Вывод для практики: универсального подхода нет — понимание различий помогает выбирать инструмент и писать более эффективный код на любом из них.

Что далее

Vue.js Пройдено
Антон Помазков
Angular Пройдено
Антон Помазков
Svelte Пройдено
Антон Помазков
Solid Пройдено
Антон Помазков
Qwik Пройдено
Антон Помазков
Общие шаблоны Пройдено
Артём Никифоров
Артём Никифоров
Будущее React Пройдено
Артём Никифоров