A React Developer's Guide to Vue.js

Chineta AdinnuChineta Adinnu
4 min read

After more than four years of building apps with React, I decided to learn Vue.js. This guide is for React developers who want to understand Vue through familiar concepts. I'll walk through similarities, key differences, and mental shifts to help you pick up Vue faster.

1. Component Syntax: JSX vs Template

  • React uses JSX, mixing JavaScript and HTML in the same file.

  • Vue uses <template> for markup, <script> for logic, and optional <style>.

React:

function Button({ label }) {
  return <button>{label}</button>;
}

Vue:

<template>
  <button>{{ label }}</button>
</template>

<script setup>
const props = defineProps(['label'])
</script>

2. State Management: useState vs ref and reactive

  • ref is like useState for primitive values

  • reactive is better for objects/arrays

React:

const [count, setCount] = useState(0)

Vue:

const count = ref(0)

For objects:

const user = reactive({ name: 'Neta' })

You update Vue state directly:

count.value++
user.name = 'Ada'

3. Derived State: useMemo vs computed

Both are used for memoized values.

React:

const total = useMemo(() => price * quantity, [price, quantity])

Vue:

const total = computed(() => price.value * quantity.value)

Vue tracks dependencies automatically.

4. Side Effects: useEffect vs watch

React:

useEffect(() => {
  fetchData()
}, [id])

Vue:

watch lets you track changes to state

watch(id, () => {
  fetchData()
})

5. Props and Events

React:

  • Props passed as JSX attributes

  • Event handlers passed down as functions

Vue:

  • Props declared using defineProps()

  • Emits handled with emit()

Child.vue:

<script setup>
const emit = defineEmits(['submit'])
const handleClick = () => emit('submit')
</script>

Parent.vue:

<Child @submit="doSomething" />

6. Children vs Slots

  • React: props.children

  • Vue: <slot />

React:

function Layout({ children }) {
  return <div>{children}</div>
}

Vue:

<template>
  <div><slot /></div>
</template>

Named slots are supported too:

<slot name="header" />

7. Conditional Rendering

React:

{isLoggedIn ? <Dashboard /> : <Login />}

Vue:

<Dashboard v-if="isLoggedIn" />
<Login v-else />

8. List Rendering

React:

{items.map(item => <li key={item.id}>{item.name}</li>)}

Vue:

<li v-for="item in items" :key="item.id">{{ item.name }}</li>

9. Forms and Two-Way Binding

React:

<input value={name} onChange={e => setName(e.target.value)} />

Vue:

<input v-model="name" />

10. Global State: Redux Toolkit vs Pinia

React: Redux, Context API Vue: Pinia (official store library)

Pinia example:

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({ name: 'Ada' }),
  actions: {
    setName(newName) {
      this.name = newName
    },
  },
})

11. Data Fetching: React Query vs Vue Query

React: React Query (useQuery) Vue: Vue Query (same API)

import { useQuery } from '@tanstack/vue-query'

const { data, isLoading } = useQuery({
  queryKey: ['jobs'],
  queryFn: () => axios.get('/api/jobs'),
})

12. Making API Calls

React:

useEffect(() => {
  const fetchData = async () => {
    const res = await fetch('/api/users')
    const data = await res.json()
    setUsers(data)
  }
  fetchData()
}, [])

Vue:

onMounted(async () => {
  const res = await fetch('/api/users')
  const data = await res.json()
  users.value = data
})

13. Context API vs Provide/Inject

React:

React uses Context to share state across components.

const ThemeContext = createContext()

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Child />
    </ThemeContext.Provider>
  )
}

function Child() {
  const theme = useContext(ThemeContext)
  return <div>{theme}</div>
}

Vue:

  • provide shares values

  • inject receives them in child components

<!-- Parent.vue -->
<script setup>
import { provide } from 'vue'
provide('theme', 'dark')
</script>

<!-- Child.vue -->
<script setup>
import { inject } from 'vue'
const theme = inject('theme')
</script>

<template>
  <div>{{ theme }}</div>
</template>

14. Custom Hooks (React) vs Composables (Vue)

React:

function useCounter() {
  const [count, setCount] = useState(0);
  return { count, increment: () => setCount(c => c + 1) };
}

Vue:

import { ref } from 'vue';

export function useCounter() {
  const count = ref(0);
  const increment = () => count.value++;
  return { count, increment };
}

Usage:

<script setup>
import { useCounter } from './counter.js'
const { count, increment } = useCounter()
</script>

<template>
    <p>{{count}}</p>
    <button @click="increment">Add</button>
</template>

15. DevTools

  • Vue has its own Vue Devtools (Chrome/Firefox)

  • Shows reactive values, component hierarchy, and Pinia stores

  • Like React Devtools but built specifically for Vue’s reactivity model

Final Thoughts

If you're comfortable with React, learning Vue won't be hard. Vue’s syntax is simpler, and its reactivity system makes many things more intuitive. ref, computed, and watch feel like natural extensions of hooks. Once you get past the template syntax, everything else starts to click.

Use this guide as your map. Start building.

2
Subscribe to my newsletter

Read articles from Chineta Adinnu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chineta Adinnu
Chineta Adinnu

Hi, I’m Chineta Adinnu! I’m a frontend developer with a passion for creating dynamic and user-friendly web experiences. On this blog, I share my journey in frontend development, from learning new technologies to implementing them in real projects. I dive into frameworks like React and Next.js, explore state management with Redux Toolkit, and offer practical tips based on my hands-on experience. My goal is to provide valuable insights and tutorials that can help others navigate the ever-evolving world of web development. Join me as I document my learning process, share challenges and solutions, and offer guidance on the latest frontend technologies. If you’re interested in tech or looking for practical advice, you’re in the right place! Feel free to connect if you have questions or want to discuss tech! Check out some of my articles on Medium: https://medium.com/@chinetaadinnu."