I Thought React Was Clean, Then I Tried Vue



This content originally appeared on DEV Community and was authored by Bunmi Oye

Why I Finally Gave Vue a Shot

As a frontend developer who’s spent a lot of time with React, learning Vue has always been on my bucket list. I finally got my hands on Vue recently and I want to share my experience, highlighting the differences, similarities, and surprises along the way.

Learning and using Vue was easier than I expected. At one point I genuinely thought, “Man, they have it easy over here.” Vue’s simple yet functional nature is what I hope to share in this post.

How a Job Application Pushed Me into Vue

I applied for a job that required Vue, and given my strength in React, I was confident I could pick it up fast. The company had other plans, though, they required me to complete an assessment using Vue.js. That turned my casual interest into a hands-on crash course.

Me and React: A Brief History

My first hands-on experience with React was in 2020, back when class components were still widely used. It was a bit of a headache to learn, but I leaned into it while appreciating the simpler functional components. I started working with React professionally at an entry level in 2021.

Why Vue, and Why Now?

Back in 2020, the options presented to me were React, Vue, or Angular. Angular seemed like it was falling out of favor (even though it wasn’t really losing Google’s support) while Vue felt a bit more alien than React (surprisingly). I sometimes wonder if starting with Vue would’ve been better, but I’m ultimately glad I picked React first. Learning Vue after React felt easier than I imagine the reverse would’ve been.

Besides needing Vue for the assessment, I’d had it in mind for a while. The job just gave me the excuse I needed.

My First Impressions of Vue

Working with Vue was actually a lot more intuitive (and fun) than I expected. Vue files reminded me of vanilla web projects; HTML, CSS, and JavaScript all in one place.

Vue components come in two flavors: the Options API and the Composition API. The Options API structures things around objects and is more declarative. The Composition API, introduced in Vue 3, is closer to the function-based style I’m used to in React. I tried the Options API briefly, but stuck with the Composition API because it felt more natural.

A typical .vue file contains three sections:

<template>
  <h1 class="greeting"> Hi mom! </h1>
</template>

<script setup lang="ts">
  import { ref } from 'vue';
  const isReact = ref<boolean>(false);
</script>

<style lang="scss" scoped>
  .greeting {
    font-style: italic;
  }
</style>
  • The <template> tag handles your rendered HTML and other components, kind of like the return() in a React component. You can also render multiple elements without wrapping them in a div, just like React fragments. (Fun fact: Vue also supports JSX.)
  • The <script setup> block is where you declare state, functions, and imports, similar to what you’d place above the return statement in React.
  • Styling is scoped by default and written in a <style> block using normal CSS selectors. It also allows using specific styling like SCSS.

Building Something Real with Vue

I built an infinite scroll photo gallery using the Unsplash API. Key features included:

  1. Keyword search via a search bar
  2. Displaying photos in a masonry-style grid
  3. Viewing each photo in a modal
  4. Auto-loading more photos when scrolling near the bottom

I will go into more detail in a future post, but here’s what stood out compared to React.

Fetching on Page Load

To load photos on page load, I used Vue’s onMounted() lifecycle hook. It’s basically Vue’s version of React’s useEffect(() => {}, []).

onMounted(() => {
  fetchPhotos();
});

Modals with <teleport> vs React Portals

For the modal, I wanted to append it directly under the <body> tag. In React, I’d use ReactDOM.createPortal, but Vue makes this incredibly simple with the <teleport> tag. Honestly, this might be my favorite Vue feature so far.

React Portal

import { createPortal } from "react-dom";

const Modal = () => {
    return createPortal(
        <div>
            <h3>This is a modal!</h3>
        </div>,
        document.body
    );
};

Vue Teleport

<teleport to="body">
    <div>
        <h3>This is a modal!</h3>
    </div>
</teleport>

Modal closed
photos in masonsry grid

Modal open
single photo opened in a modal

Passing Props to Child Components

To pass the selected photo to the modal, I used props. In Vue, you pass props using the : shorthand for v-bind:

<template>
    <Gallery :photos="photos" />
</template>

Infinite Scroll with Intersection Observer

To implement infinite scrolling, I set up an IntersectionObserver inside the onMounted() hook and cleaned it up using onBeforeUnmount(), just like you would with a cleanup function in React.

onMounted(() => {
  const observer = new IntersectionObserver(loadMorePhotos);
  observer.observe(loadMoreRef.value);

  onBeforeUnmount(() => observer.disconnect());
});

Skeleton loaders when scrolling down
image showing skeleton loaders when newring the bootom of the screen

Final Thoughts on Vue vs React

React and Vue share many similarities, but Vue feels cleaner and more elegant in some areas. That said, I haven’t tackled advanced topics in Vue yet; like lazy loading, memoization, or server-side rendering (SSR). I know Vue might not have 1:1 equivalents for everything in React, and that’s okay. I’m excited to explore further and share what I learn.

Tooling I Used

  • ⚡ Vite – for super fast development
  • 🟦 TypeScript – for static typing
  • 🌄 Unsplash API – for fetching beautiful images
  • 🧱 Vue 3 – using the Composition API
  • 🖼 SCSS – scoped in .vue files for styling

🔗 View the code here

Thanks for reading! I’d love to hear your thoughts and experiences with Vue or React. Have you tried switching between them? What stood out to you the most? Let me know in the comments.

Happy coding. 🚀


This content originally appeared on DEV Community and was authored by Bunmi Oye