Migrating from Vue 3 to React

Overview

Moving from Vue 3 to React is a framework rewrite, not a data migration - there's no file to export and import, because the two frameworks represent components, state, and templates in fundamentally different ways. Vue 3 writes components as Single File Components with a <script setup> block, a <template> block, and Vue's own reactivity primitives (ref(), reactive(), computed()); React writes them as JavaScript functions returning JSX. Some pieces of the surrounding stack (build tooling, routing, testing) have a clean named equivalent on the other side, but the component code itself has no automated converter - porting is manual, component by component, optionally staged through an interop layer while the rewrite is in progress.

This guide covers moving from Vue to React — see each platform's release history and version notes on its technology page.

Want a plan tailored to your Vue 3 → React migration?

Get my plan

What transfers cleanly from Vue 3 to React

  • Props and events follow the same shape on both sides even though the syntax differs: Vue declares incoming props with defineProps() (passed as :prop="value" attributes from a parent) and a child communicates up by calling defineEmits()-declared events, heard via @event-name="handler"; React passes data via JSX attributes read as function parameters, with a child calling a callback prop the parent supplies. The concept - props down, callback/emit up - carries across directly.
  • Vue's <slot> and React's children prop are the same mechanism for parent-supplied child content, so any component built around composing children maps onto React's children pattern without a conceptual rewrite.
  • Routing has a direct role-equivalent on each side: Vue Router (the official router, maintained by the Vue core team) and React Router (a separate, community/open-governance project React's own docs recommend for new projects) both provide route matching, nested/dynamic routes, and multiple history modes, so the routing structure of an app - not its code - carries across.
  • Build tooling converges on Vite for both ecosystems - Vue 3's official scaffolding (npm create vue@latest) is Vite-based with what Vue's docs call "first-class Vue SFC support," and React's own docs list Vite among the supported build-tool options - so dev-server, plugin, and env-var configuration transfers more easily than component code does.
  • Global state management has a like-for-like named target: Pinia is Vue's officially recommended state library, maintained by the Vue core team, and Redux Toolkit is React's official, recommended toolkit for Redux-based state - both occupy the same "official global-state solution" role even though the APIs are different.

What does not transfer

  • Vue's template syntax and JSX are not mechanically interchangeable. Vue's <template> is HTML-based with its own directive syntax (v-if, v-for, @click, :attr) compiled ahead of time, while JSX is JavaScript with markup - arbitrary expressions, {} interpolation, every element ultimately a function call. Porting a component means rewriting its render logic in the target syntax, not a find-and-replace.
  • There is no official Vue-to-React codemod. Vue's own migration tooling (the @vue/compat migration build, community vue-codemod tools) targets the Vue 2-to-3 upgrade path within Vue itself, not a cross-framework conversion, and React's react-codemod collection only transforms within React (class-to-hooks patterns, PropTypes, lifecycle renames) with no ability to import from Vue. Migration is manual, component by component.
  • Vue's reactivity primitives (ref(), reactive(), computed()) and React's Hooks-based state model (useState, called only at the top of a component, never inside conditions or loops) are different systems, not a drop-in swap - each component's state logic has to be rewritten in the target model rather than translated.
  • Module Federation is documented as a generic, framework-agnostic way to compose separately-built bundles, but webpack's own concept page gives no explicit Vue-plus-React mixing example - treat it as generically possible for staging this migration, not as a documented, off-the-shelf pattern for this specific pair.

Effort drivers

  • Whether the app relies on Pinia (or the older Vuex) for global state - that state model has to be rebuilt on React's Hooks/Context pattern or Redux Toolkit, since there's no automated conversion between the two.
  • How much of the component tree uses the Options API rather than <script setup> - Vue 3 fully supports both, so a codebase that predates widespread <script setup> adoption adds an extra internal-Vue consideration on top of the eventual React rewrite.
  • Whether the app can be staged through an interop layer at all: veaury (bidirectional Vue-3/React interop) requires the converted components to be client-rendered, with no documented SSR support, so an SSR Vue app narrows which staging approach is viable.
  • How much of the app's build tooling already sits on Vite - since both ecosystems converge there, an app already on Vue 3's Vite-based scaffolding has less build-tooling work ahead of it than one still on Vue CLI.

Recommended approach

Since there's no automated converter for this pair, plan the migration as a staged rewrite rather than a tool-driven one. Two documented ways to run both frameworks side by side while you work: veaury, a bidirectional Vue-3/React interop library that lets you mount React components inside Vue 3 (or the reverse) and swap components over time - usable only for client-rendered components, since it has no documented SSR support; or single-spa, a micro-frontend framework that explicitly supports mixing React and Vue on the same page without a refresh, letting you mount a new React app alongside the existing Vue 3 app and migrate route by route or feature by feature.

Whichever staging approach you use (or if you skip staging entirely), the component rewrite itself is manual: convert each component's template render logic into JSX, translate Vue's ref()/reactive()/computed() into React Hooks, and move global state from Pinia onto Redux Toolkit (or component-local useState/Context for simpler needs).

Reuse what does carry across directly - swap Vue Router for React Router while keeping the same route structure, Vue Test Utils for React Testing Library, Element Plus or PrimeVue for MUI or Ant Design, VeeValidate for React Hook Form, and Vue's built-in <Transition> component for Motion. Standardize the build setup on Vite for both sides during the transition, since that's the one place the two ecosystems already converge.

FAQ

Is there a tool that automatically converts Vue 3 code to React?
No. There's no official Vue-to-React codemod - Vue's own migration tooling only targets the Vue 2-to-3 upgrade within Vue itself, and React's react-codemod collection only transforms within React. Migration is manual, component by component, optionally staged through veaury or single-spa.
Can I run Vue 3 and React in the same app during migration?
Yes, two documented ways. veaury is a bidirectional interop library - use Vue 3 components inside React, or React components inside Vue 3 - but its converted components need to be client-rendered, with no documented SSR support. single-spa is a micro-frontend framework that explicitly supports mixing Vue and React on the same page, letting you mount a new React app alongside the existing Vue 3 app and migrate route by route.
What's the React equivalent of Pinia?
Redux Toolkit is the closest official-role equivalent - it's React's official, recommended toolkit for Redux-based state, occupying the same "recommended global-state library" role Pinia holds for Vue. Simpler apps can also use React's built-in useState/useReducer and Context API instead.
Do I need to rewrite my Vue 3 templates from scratch for React?
Yes, the render logic does. Vue's <template> is HTML-based with its own directive syntax compiled ahead of time, while JSX is JavaScript-with-markup compiled as function calls - they aren't mechanically interchangeable, and there's no codemod that does this conversion for you.
What build tool should I use for a React rewrite of a Vue 3 app?
Vite, on both sides. Vue 3's official scaffolding tool is Vite-based, and React's own docs list Vite as a supported build-tool option - it's the one part of the stack where the two ecosystems already converge, which simplifies porting dev-server and plugin configuration even though it doesn't simplify porting component code.

Ready to see what this actually takes?

Get my plan

Related migrations