The post has been translated automatically. Original language: Russian
A dispute that is older than dinosaurs
Since the Mesozoic, there have been holivars on the topic of "which library is better for the frontend — React or Vue?". Also, Angular and Svelte sometimes take over the attention next to them, but most often it is the first two libs that collide with their foreheads — as the most popular on the market and with the lowest entry threshold for starting in Frontend.
But today I don't want to talk about what's better or worse. Each tool solves its own problems, and the final decision on which technology is best suited for a project or product is made by an engineer, taking into account all the introductory and nuances. I'm interested in something else. In October 2025, the React team released a stable version of React Compiler 1.0, a tool that takes over the memoization that has been on the developer's shoulders for years. In Vue, you hardly have to think about this: reactivity initially updates only what depends on the changed data. So does React adopt the Vue philosophy, where optimization is the tool's concern, not ours? In short: for DX— yes, for architecture— no. Let's figure out why.
The optimization problem in React
Before diving into the essence of the innovation, let's look at the problem that has become the catalyst for changes in the React approach. It's all the fault of manual component optimization. Firstly, it degrades the readability of the code. Secondly, it adds a cognitive burden to the developer: you need to monitor arrays of dependencies and keep in mind the stability of links. A forgotten dependency leads to outdated closures, and an unstable dependency object imperceptibly turns useMemo into a recalculation on each render.
At the same time, developers sometimes memorize things that do not need to be memorized at all, although many performance problems can be solved with competent architecture and component decomposition. I think every React developer has come across the God component at least once, in which countless optimizations for the sake of optimizations are combined with at least long arrays of dependencies in each useMemo and useCallback.
What do the React developers themselves think about this ?
In order not to be unfounded, let's see what the React developers themselves say about this. Back in 2021, at the React Conf, Xuan Huang raised this issue in the report "React without memo". For the first time, the React team showed a possible solution there — the React Forget compiler, to which you can delegate memoization and thereby save developers from mistakes in manual interface optimization.
In 2024, in the React blog (React Labs: What We've Been Working On – February 2024), the team explicitly wrote that manual memoization did not suit them. They called it a compromise that is at odds with their vision of how React should update the UI.:
Manual memoization is a reasonable compromise, but we weren't satisfied. Our vision is for React to automatically re-render just the right parts of the UI when state changes, without compromising on React's core mental model.React Labs, February 2024
In the same post, they said that the project that Xuan Huang showed grew into React Compiler and is already working in production on Instagram. In May 2024, the compiler was opened in open source, and in October 2025, the stable version 1.0 was released, and now it can be integrated into your projects.
It is important to understand that the compiler does not eliminate the need for a good architecture. It removes the routine of manual memoization from the developer and insures against typical errors, and the decomposition and thoughtful structure of components remain our task.
So what's up with Vue?
Now let's get back to where we started. React Compiler automates at the build stage what Vue, thanks to its reactivity, has been doing in runtime from the very beginning. When I first got acquainted with Vue after React, it struck me that the state can be mutated directly — without setters, without arrays of dependencies, and without useMemo/useCallback. The setup function is executed once per component instance, and Vue itself monitors and monitors which reactive data is being read in the template, computed, and watchEffect. Here lies the main difference in the ideas of drawing interfaces.
- When the state changes, React re-calls the component's function as a whole, and by default, all of its descendants. Then, at the reconciliation stage, it compares the new tree with the previous one and applies only the found changes to the DOM. React doesn't know in advance exactly what has changed — it recalculates and compares. Hence the extra re-renders, which previously had to be managed manually. This is exactly what the React Compiler does: it caches values and JSX elements, and React skips redrawing everything that hasn't changed.
- During rendering, Vue records which reactive properties the component has read. When a property changes, Vue knows exactly which components need to be updated, and it doesn't even touch the rest. The reactive data itself reports changes, and there is no need to recalculate "just in case". For more information, see the Reactivity in Depth documentation section.
Let's look at the same component. This is how it looks in React with manual optimization:
// React: each time the state changes, the function is executed anew,
// so filtered and handleClick have to be wrapped in memo hooks
function List({ items }) {
const [query, setQuery] = useState('');
const filtered = useMemo(
() => items.filter(i => i.includes(query)),
[items, query]
);
const handleClick = useCallback(() => setQuery(''), []);
// ...
}And so — in Vue:
<!-- Vue: setup is performed once, computed knows its dependencies by itself -->
<script setup>
const props = defineProps(['items'])
const query = ref('')
const filtered = computed(() =>
props.items.filter(i => i.includes(query.value))
)
const handleClick = () => { query.value = '' }
</script>With React Compiler, the React version can be written in the same "naive" way (in the good sense of the word) as in Vue, without useMemo and useCallback: the compiler will arrange the memoization.
It turns out that both tools have come to the same result — the developer no longer needs to manually explain to the library what to recalculate and what not to, but in different ways. React retained its "UI is a pure function of an immutable state" model and shifted optimization to the compiler. Vue initially relied on point reactivity and now goes even further: in the optional Vapor Mode (Vue 3.6, still experimental), it abandons the virtual DOM and updates the DOM directly.
However, the mechanisms still vary. In React, the component's function is executed anyway when its state changes, just by reusing the cached results. In Vue, components that do not depend on the changed data are not redrawn at all. Therefore, the compiler does not make React a "second Vue": it removes the most painful part of the difference, but not the philosophy itself.
🏁 Summary
Let's go back to the question from the beginning: has React become Vue? For DX, yes: you can now write components "naively" without thinking about memoization, as it always has been in Vue. Architecturally— no: React still recalculates and compares, while Vue reacts pointwise to changes.
What does this mean in practice? For a React developer, instead of manual optimizations, you can do things that the compiler won't do for us: architecture, decomposition, and thoughtful state management. For someone who is choosing between React and Vue, the argument "there is no need to mess with memoization in Vue" has noticeably weakened. The choice increasingly comes down not to performance, but to which mental model is closer to you: explicit immune updates or transparent reactivity.
🦖 Спор, который старше динозавров
Ещё со времён мезозоя ведутся холивары на тему того, «какая же библиотека для фронтенда лучше — React или Vue?». Также рядом с ними иногда внимание забирают на себя Angular и Svelte, но чаще всего лбами сталкивают именно первые две либы — как самые популярные на рынке и с самым низким порогом входа для старта во Frontend.
Но сегодня я хочу поговорить не о том, что из этого лучше или хуже. Каждый инструмент решает свои задачи, а окончательное решение о том, какая технология лучше подходит для проекта или продукта, принимает инженер с учётом всех вводных и нюансов. Меня интересует другое. В октябре 2025 года команда React выпустила стабильную версию React Compiler 1.0 — инструмента, который берёт на себя мемоизацию, годами лежавшую на плечах разработчика. Во Vue об этом почти не приходится думать: реактивность изначально обновляет только то, что зависит от изменённых данных. Так что же, React принимает философию Vue, где оптимизация — забота инструмента, а не наша? Коротко: по DX — да, по архитектуре — нет. Давайте разбираться, почему.
🐌 Проблема оптимизации в React
Прежде чем погружаться в суть нововведения, посмотрим на проблему, которая стала катализатором изменений в подходе React. Виной всему ручная оптимизация компонентов. Во-первых, она ухудшает читаемость кода. Во-вторых, она добавляет разработчику когнитивной нагрузки: нужно следить за массивами зависимостей и помнить о стабильности ссылок. Забытая зависимость приводит к устаревшим замыканиям (stale closures), а нестабильный объект в зависимостях незаметно превращает useMemo в пересчёт на каждом рендере.
При этом разработчики порой мемоизируют то, что в мемоизации вовсе не нуждается, хотя многие проблемы производительности можно решить грамотной архитектурой и декомпозицией компонентов. Думаю, каждый React-разработчик хотя бы раз сталкивался с God component, в котором бесчисленные оптимизации ради оптимизаций соседствуют с не менее длинными массивами зависимостей в каждом useMemo и useCallback.
👨💻 Что об этом думают сами разработчики React
Чтобы не быть голословным, давайте посмотрим, что об этом говорят сами разработчики React. Ещё в 2021 году на React Conf Xuan Huang поднял эту проблему в докладе «React without memo». Команда React впервые показала там возможное решение — компилятор React Forget, которому можно делегировать мемоизацию и тем самым избавить разработчиков от ошибок в ручной оптимизации интерфейса.
В 2024 году в блоге React (React Labs: What We've Been Working On – February 2024) команда прямо написала, что ручная мемоизация их не устраивает. Они назвали её компромиссом, который расходится с их видением того, как React должен обновлять UI:
Manual memoization is a reasonable compromise, but we weren't satisfied. Our vision is for React to automatically re-render just the right parts of the UI when state changes, without compromising on React's core mental model.React Labs, февраль 2024
В том же посте рассказали, что проект, который показывал Xuan Huang, вырос в React Compiler и уже работает в продакшене в Instagram. В мае 2024 года компилятор открыли в open source, а в октябре 2025 вышла стабильная версия 1.0, и теперь его можно интегрировать в свои проекты.
Важно понимать: компилятор не отменяет необходимости в хорошей архитектуре. Он снимает с разработчика рутину ручной мемоизации и страхует от типичных ошибок, а декомпозиция и продуманная структура компонентов остаются нашей задачей.
🤔 Так что там с Vue?
Теперь вернёмся к тому, с чего начали. React Compiler автоматизирует на этапе сборки то, что Vue благодаря своей реактивности делал в рантайме с самого начала. При первом знакомстве с Vue после React меня поразило, что состояние можно мутировать напрямую — без сеттеров, без массивов зависимостей и без useMemo/useCallback. Функция setup выполняется один раз на экземпляр компонента, а Vue сам отслеживает, какие реактивные данные читаются в шаблоне, computed и watchEffect, и при их изменении обновляет только то, что от них зависит. Тут и кроется главное различие в идеях отрисовки интерфейсов.
- React при изменении состояния заново вызывает функцию компонента целиком, а по умолчанию и всех его потомков. Затем на этапе reconciliation он сравнивает новое дерево с предыдущим и применяет к DOM только найденные изменения. React не знает заранее, что именно поменялось, — он перевычисляет и сравнивает. Отсюда и лишние ререндеры, которыми раньше приходилось управлять вручную. Именно эту работу React Compiler и сокращает: он кэширует значения и JSX-элементы, и React пропускает перерисовку всего, что не изменилось.
- Vue во время рендера записывает, какие реактивные свойства прочитал компонент. Когда свойство меняется, Vue точно знает, каким компонентам нужно обновиться, а остальные даже не трогает. Реактивные данные сами сообщают об изменениях, и перевычислять «на всякий случай» не нужно. Подробнее — в разделе документации Reactivity in Depth.
Посмотрим на один и тот же компонент. Так он выглядит в React с ручной оптимизацией:
// React: при каждом изменении состояния функция выполняется заново,
// поэтому filtered и handleClick приходится оборачивать в memo-хуки
function List({ items }) {
const [query, setQuery] = useState('');
const filtered = useMemo(
() => items.filter(i => i.includes(query)),
[items, query]
);
const handleClick = useCallback(() => setQuery(''), []);
// ...
}А так — во Vue:
<!-- Vue: setup выполняется один раз, computed сам знает свои зависимости -->
<script setup>
const props = defineProps(['items'])
const query = ref('')
const filtered = computed(() =>
props.items.filter(i => i.includes(query.value))
)
const handleClick = () => { query.value = '' }
</script>С React Compiler React-версию можно писать так же «наивно» (в хорошем смысле этого слова), как во Vue, — без useMemo и useCallback: мемоизацию расставит компилятор.
Получается, что оба инструмента пришли к одному результату — разработчику больше не нужно вручную объяснять библиотеке, что пересчитывать, а что нет, — но разными путями. React сохранил свою модель «UI — чистая функция от иммутабельного состояния» и переложил оптимизацию на компилятор. Vue изначально сделал ставку на точечную реактивность и теперь идёт ещё дальше: в опциональном Vapor Mode (Vue 3.6, пока экспериментальный) он отказывается от виртуального DOM и обновляет DOM напрямую.
При этом механизмы по-прежнему различаются. В React функция компонента при изменении его состояния всё равно выполняется, просто с переиспользованием закэшированных результатов. Во Vue компоненты, которые не зависят от изменённых данных, не перерисовываются вовсе. Поэтому компилятор не делает React «вторым Vue»: он убирает самую болезненную часть разницы, но не саму философию.
🏁 Итог
Вернёмся к вопросу из начала: стал ли React Vue? По DX — да: писать компоненты теперь можно «наивно», не думая о мемоизации, как это всегда было во Vue. По архитектуре — нет: React по-прежнему перевычисляет и сравнивает, а Vue точечно реагирует на изменения.
Что это значит на практике? Для React-разработчика — что вместо ручных оптимизаций можно заниматься тем, что компилятор за нас не сделает: архитектурой, декомпозицией и продуманным управлением состоянием. Для того, кто выбирает между React и Vue, — что аргумент «во Vue не нужно возиться с мемоизацией» заметно ослаб. Выбор всё больше сводится не к производительности, а к тому, какая ментальная модель вам ближе: явные иммутабельные обновления или прозрачная реактивность.