Concurrent Mode был важной темой для React в тот период, когда команда искала способ сделать интерфейсы более отзывчивыми под нагрузкой. Сегодня этот пост полезнее читать не как инструкцию «что срочно включить», а как объяснение идей, из которых позже выросли современные concurrent-возможности React.
Главная мысль была простой: если рендеринг тяжелый, интерфейс не должен выглядеть зависшим. React хотел получить больше контроля над тем, какие обновления важнее для пользователя прямо сейчас, а какие можно отложить на долю секунды.
Обновлено 17 марта 2026: статья переписана как исторический разбор. Устаревшие ожидания от отдельного Concurrent Mode убраны, а связь с современными concurrent-возможностями React показана напрямую.
- Концепция Concurrent Mode
- Опыт пользователя
- Прерываемый рендеринг
- Преднамеренные последовательности загрузки
- Как тогда включали Concurrent Mode
- Что из этого выросло дальше
- Итог
Концепция Concurrent Mode
Как я уже упоминал во введении, концепция Concurrent Mode не нова. Возьми процессоры в качестве примера. Процессоры получили scheduler (планировщик задач), который расставляет приоритеты для наиболее важных задач, когда ресурс доступен. То же самое касается компилятора JavaScript, но у него есть один поток (single thread) для взаимодействия с пользователем (поток пользовательского интерфейса), который мы должны использовать с умом. Если этот поток «зависает» из-за перегрузки работы, он не может реагировать на новые события, пока работа не будет завершена. Concurrent Mode хочет предотвратить это, создав несколько «мини-потоков» в основном потоке пользовательского интерфейса, и с помощью своего собственного планировщика он может поддерживать скорость отклика.
Опыт пользователя
Трудно избежать проблемы многократного рендеринга, потому что даже если твоё приложение имеет хорошую производительность, устройство, которое есть у пользователя, может быть недостаточно сильным для его обработки. Факторы, такие как скорость сети и возможности устройства, могут привести к зависанию приложения, даже если ты хорошо справился с throttling и debouncing.
Есть некоторые события, например, наведение курсора на элементы или ввод в поле ввода, которые хотелось бы, чтобы происходили немедленно. Если твоё устройство занято рендерингом списка, эффект наведения не будет отображаться до того, как он будет выполнять предыдущую задачу. Когда React начинает рендерить, ты не можешь остановить его, пока этот процесс не будет завершен. Concurrent Mode будет фокусироваться на человеческом взаимодействии; простые задачи, такие как наведение и прокрутка, должны выполняться мгновенно, в то время как переход на новые сайты и загрузка новых данных более приемлемы, так как занимают больше времени.
Прерываемый рендеринг
В параллельном режиме рендеринг может быть прерван. Если пользователь инициирует другое более важное событие, он приостанавливает рендеринг и выполняет желаемое задание, прежде чем вернуться к исходному заданию, чтобы его завершить. Степень важности определяется эвристикой, чтобы знать, как расставить приоритеты в этом новом обновлении. Это (надеюсь) сделает приложение более отзывчивым!
Я не думаю, что мы должны полагаться на тот факт, что Concurrent Mode решит все наши проблемы с производительностью. Тем не менее считаю, что он будет хорошим помощником в тяжелых React-приложениях.
Преднамеренные последовательности загрузки
Это обычное действие, когда ты переходишь на новый сайт на своем сайте, и одновременно хочешь получить данные. Но раздражает, когда тебя перенаправляют на новую страницу без содержимого или показывают индикатор загрузки. Что, если React может задержать нас на предыдущей странице чуть дольше, чтобы пропустить состояние загрузки? Когда пользователь запустил действие, которое приводит к переходу, React может начать строить новую страницу в памяти и подождать с обновлением DOM, пока она не будет готова. При этом «старая» страница остаётся интерактивной.
Именно из этой идеи позже вырос стабильный useTransition. Если читать статью сегодня, лучше держать в голове уже современный API:
const [isPending, startTransition] = useTransition();startTransition помечает обновление как менее приоритетное, а isPending показывает, что переход еще не завершен. Практический смысл в том, что тяжелое обновление не должно ломать отзывчивость более важного взаимодействия.
Пример с startTransition в качестве обработчика onClick для кнопки, которая загружает асинхронные данные:
<button
disabled={isPending}
onClick={() => {
startTransition(() => {
fetchSomeData();
});
}}
>
Load data
</button>Как тогда включали Concurrent Mode
На момент публикации параллельный режим ещё не был выпущен стабильно и был доступен в теге experimental. Поэтому команды ниже стоит воспринимать как исторический контекст, а не как текущую рекомендацию для production-проекта.
Чтобы получить версию с параллельным режимом, тебе нужно установить эту экспериментальную версию React:
npm install react@experimental react-dom@experimental
# или: yarn add react@experimental react-dom@experimentalДалее, чтобы включить его, тебе просто нужно внести некоторые изменения в свой основной файл и использовать createRoot из ReactDOM:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'
// До Concurrent Mode:
const rootEl = document.getElementById('root')
ReactDOM.render(<App />, rootEl)
// После Concurrent Mode:
const root = ReactDOM.createRoot(rootEl)
root.render(<App />)Кроме того, чтобы иметь возможность использовать параллельный режим, настоятельно рекомендуется использовать строгий режим (StrictMode).
Что из этого выросло дальше
Дата стабильной версии Concurrent Mode тогда ещё не была объявлена, и именно поэтому было важно следить не столько за флагом, сколько за идеями вокруг приоритетов рендера, переходов и отзывчивости интерфейса.
Если читать этот материал сегодня, полезнее всего вынести две вещи: тяжелый рендеринг нужно измерять и разбирать отдельно, а оптимизация UI начинается не с волшебного режима, а с понимания того, какие обновления пользователь действительно чувствует.
Итог
Даже если сам термин Concurrent Mode со временем ушел в историю, идея никуда не делась: React должен помогать интерфейсу оставаться отзывчивым, когда работа становится тяжелой. Поэтому этот материал лучше воспринимать как фундамент для понимания переходов, приоритетов рендера и современных оптимизаций, а не как руководство по включению старого экспериментального режима.