Skip to main content
EJ Centeno

What I Learned Migrating from Vue.js to React After 3 Years

January 15, 2026 · 6 min read

What I Learned Migrating from Vue.js to React After 3 Years

I spent more than three years writing Vue.js full-time at MYCURE, a healthcare SaaS company serving clinics and hospitals across the Philippines. I knew Vue deeply — the Options API, then the Composition API when Vue 3 dropped, Vuex, Pinia, vue-router, Nuxt.js, Vuetify. It was my professional home.

Then in February 2026, I joined C3 Interactive Manila and landed on a React project on day one.

This is an honest account of what that transition felt like — the friction, the surprises, and the mental models that actually transferred.

The Mental Shift That Took the Longest

The hardest part wasn't syntax. It was unlearning the "template first" instinct. In Vue, your component starts with a template block that reads like HTML with superpowers — v-if, v-for, v-model. The markup and the logic feel separate even when they're in the same file.

In React, JSX puts everything in one place. At first, this felt messy. I kept wanting to separate things. But after a few weeks, something clicked: JSX is just a function call. Once I started thinking about components as functions that return UI, React's model started to feel natural, almost elegant.

Composition API vs. Hooks — Closer Than You'd Think

Coming from Vue 3's Composition API, React hooks felt familiar in spirit but different in practice. In Vue, ref() and reactive() give you explicit reactivity. In React, useState and useReducer manage state, but the reactivity model is push-based — you trigger a re-render by calling the setter.

The biggest gotcha for me was stale closures in useEffect. In Vue, the Composition API's reactivity system handles dependencies automatically. In React, you have to declare your dependencies in the dependency array, and if you forget one, you get subtle bugs where your effect is working with old values. I got burned by this twice in my first week.

On the other hand, custom hooks are a pleasure to write. The pattern of extracting logic into reusable hooks is something Vue's composables do too, but the React ecosystem has a decade of examples to learn from.

Vuex and Pinia vs. Zustand

At MYCURE, I used Vuex for most of my time there, then migrated some modules to Pinia. Pinia felt like a significant improvement — simpler API, TypeScript support out of the box, no boilerplate mutations.

At C3, we use Zustand for client-side state. My first reaction was: this is tiny. The entire store definition is a single function call. No actions/mutations distinction, no modules pattern. Just a store that holds values and the functions that update them.

After building real features with it, I've come to appreciate the simplicity. Zustand doesn't enforce a pattern on you, which means you have to enforce it yourself. For our team, we decided early on to keep stores flat and colocate the actions close to the state they modify. That discipline matters more in Zustand than it did in Pinia.

vue-router vs. react-router

Both handle routing well. The biggest practical difference I noticed is that react-router v6 embraced a more declarative, JSX-based syntax for defining routes, while vue-router keeps routes as configuration objects. I found the React approach slightly more composable but less scannable at a glance.

One thing I missed from Vue: the RouterView component with named slots for layouts. In React, you build layout components by composition. It's more flexible but requires more thought upfront.

What Was Harder Than Expected

The ecosystem size. React has a massive ecosystem, and that means more options, more fragmentation, and more decisions. In Vue, there are usually one or two obvious choices. In React, there are five ways to do everything and blog posts arguing for each.

Also, the amount of boilerplate in certain performance patterns. useCallback, useMemo, React.memo — performance optimization in React requires more explicit decisions than Vue's built-in reactivity system.

What Was Surprisingly Easy

The component model. Props down, events up (or callbacks down, in React's case). The mental model is the same. If you understand parent-child communication in Vue, you understand it in React.

TypeScript integration was also smoother than expected. I was already using TypeScript in Vue projects, and the transition to typing React components felt natural. The main difference is typing component props with interfaces vs. Vue's defineProps with generics.

My Advice for Vue Devs Making the Switch

Give yourself two weeks before judging. The first week will be frustrating. The second week, things will start to click. By week three, you'll be productive.

Learn hooks deeply before anything else. useState, useEffect, useCallback, useMemo, and useContext cover 90% of what you'll need. Don't try to learn an abstraction on top of them before you understand the primitives.

And embrace the JavaScript nature of JSX. Stop trying to write it like a template. Write it like a function that returns UI, because that's exactly what it is.

← Back to all posts