Learning React / Next.js from a Vue developer’s perspective

First things first, I wouldn’t necessarily consider myself a “Vue Developer”. I have a few years of experience working in Vue, but I’m by no means a professional. I started learning Vue in 2020, but only really started building projects with it in late 2021. Since then it’s been my primary framework, and over the past 7 months I’ve been programming in Vue almost every day building my latest project Rack Manage. As I’ve been using Vue more and more, I’ve found that it may have been a bad decision for such a complex project. While I thoroughly enjoy programming in Vue, time and time again I’ve run into problems with libraries that seem to have no community in Vue but a massive community in React.

As my project has gotten more complex and I’ve had to add more and more server functions, I’ve looked into using Nuxt but again have been disappointed in it’s community support and documentation. I want to love Vue, but looking at the number of large businesses using React vs Vue alone has me worried for its future and support, and as a developer actively looking for jobs, I’ve been asked in interviews if I knew React, which makes me want to at least give it a try and build my skills in hopes of getting a job. I also want to learn TypeScript, but Vue seems to be behind React in terms of TypeScript support.

As tough as it is to abandon a framework after 7 months of development, I’ve made the decision to migrate Rack Manage to Next.js. While this is still in progress, this post is meant to be a quick beginners guide with some connections between concepts and syntax of Vue and React / Next.js that I have learned after a few days of using Next.js. I’ve been trying to find similar blog posts and YouTube videos on this topic, but again with the lack of community support, this sort of documentation was lacking, so I hope this helps some people out there in a similar situation.

Some other good resources I found on this topic are:

Overview

At it’s core, React and Vue are very similar. One way to think about this is that “React is like writing HTML in your Javascript, Vue is like writing Javascript in your HTML”. React uses JSX instead of HTML templates like Vue. While the HTML parts of your components may be fairly easy to translate over to React, there are a few key differences in the syntax. Both Vue and React use a virtual DOM, although I’ve already realized that it is more difficult to interact with the rendered DOM in React than Vue, where I was using third party libraries that modify the DOM which required a bit of work to migrate to React. Vue and React are also both component-based and support a composition API.

class vs className

In JavaScript, “class” is a reserved keyword, so to use classes in JSX, an extension of JavaScript, we have to use “className” instead. This is a direct translation from our Vue components where

Vue
<p class="text-lg text-white mt-4 font-semibold">
    Example Text
</p>

becomes

JavaScript
<p className="text-lg text-white mt-4 font-semibold">
    Example Text
</p>

Dynamically assigning classes therefore has a slightly altered syntax.

Vue:

Vue
 <div class="sm:flex flex-grow items-center"
      :class="[navbarOpen ? 'block' : 'hidden']" >

React:

JavaScript
<div className={
       "sm:flex flex-grow items-center" +
       (navbarOpen ? " block" : " hidden")
   } >

Props (v-bind)

Another key but straightforward difference in syntax is how you pass props to components in Vue vs React. While Vue uses v-bind or the : shortcut, React uses curly braces to assign dynamic props (JS expressions). In this case, a basic prop like

Vue
<Stage :width="configKonva.width" :height="configKonva.height">

in Vue, becomes

JavaScript
<Stage width={configKonva.width} height={configKonva.height}>

in React.

Another difference are object props like inline styles. While Vue lets you define styles exactly like HTML:

Vue
<span style="font-family: 'Montserrat Alternates'">...</span>

React requires you pass a JavaScript style object like so:

JavaScript
<span style={{ fontFamily: "'Montserrat Alternates'" }} >...</span>

kebab-case vs camelCase

As you may have noticed from the previous example with font-family vs fontFamily, while Vue prefers kebab-case, JSX and React use camelCase for all attributes. One place you may notice this are link tags where attributes like charset and crossorigin must be capitalized in React.

Vue:

Vue
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />

React:

JavaScript
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />

Embedding Variables ({{}} vs {})

When placing dynamic content inside of a component, Vue uses the mustache templating syntax with double curly braces, while JSX inserts JavaScript expressions with single curly braces.

Vue:

Vue
<span>Message: {{ msg }}</span>

React:

JavaScript
<span>Message: { msg }</span>

Comments

Similarly, where Vue uses HTML style comments like <!-- comment -->, React uses JS style comments inside of a JS expression, like {/* comment */}

Rendering Lists of Components

When generating components by iterating over a list, React uses the JavaScript map operator, unlike Vue’s v-for directive.

Vue:

Vue
<line v-for="item in lines" :key="item.id" :config="{points: item.points}"/>

React:

JavaScript
{lines.map((line,index)=> {
    return <Line key={index} points={line.points} />
})}

Conditional Rendering (v-if / v-show)

Conditional rendering is a bit more involved in React, where we can’t simply add a v-if to our component. Instead, we need to wrap the return statement of our component in an if expression, wrap the element in an expression, or wrap the value in an expression.

Vue:

Vue
<h1 v-if="awesome">Vue is awesome!</h1>

React (Example 1):

JavaScript
if (awesome) {
    return <h1>React is awesome!</h1>
}

React (Example 2):

JavaScript
{ awesome && <h1>React is awesome!</h1> }

React (Example 3):

JavaScript
<h1>{ awesome && "React is awesome!" }</h1>

Also note that JSX expressions can only have one root element, so conditionals of more than one element must be wrapped in an empty fragment tag like so:

JavaScript
{ awesome && <><h1>React is awesome!</h1><h2>React is cool!</h2></> }

Event Handlers

While Vue uses the inline v-on:click="handler" or @click="handler" shortcut, React uses a more traditional onClick attribute.

Vue:

Vue
<button @click="_iub.cs.api.openPreferences()" />

React:

JavaScript
<button onClick={() => {window._iub.cs.api.openPreferences()}} />

Lifecycle Hooks

While Vue has many different lifecycle hooks such as setup, mouted, update, unmounted, beforeUnmount, etc. React primarily uses the useEffect hook. In functional components, you can use the componentDidUpdate and componentWillUnmount hooks, but class components need to utilize useEffect instead.

useEffect is more versatile, however, as you can specify a list of dependencies to useEffect to trigger a call every time any of the dependencies changes.

For example, a useEffect with no dependencies (an empty array as the second argument) will only run on the initial render:

JavaScript
useEffect(() => {
    console.log("Run on initial render");
}, []);

To trigger a call on unmount, you can return a function as the result of the useEffect, for example:

JavaScript
useEffect(() => {
 return () => {
   console.log("Run on unmount");
 };
}, []);

To trigger a call every time a state or variable changes, pass that variable as a dependency like so:

JavaScript
useEffect(() => {
   console.log(`var1 has changed: ${var1}`);
}, [var1]);

Basic State & Reactivity

In Vue, every component automatically has it’s own state and variables in the data object are reactive, allowing us to mutate values directly from anywhere in the code. React on the other hand requires the use of useState to initialize our state variable, along with a mutation function that will be called instead of directly mutating the variable, similar to using a method action in Vue.

Vue (Direct Mutation):

Vue (Method Action):

React:

Conclusion

While I still prefer the syntax of Vue, largely because it’s what I’m comfortable with, there’s no denying that React is powerful and can do everything that Vue can, along with the added benefit of community support, which I have already started to notice in the modules I’m using. I’ve also noticed that it’s much easier for me to use dynamic images out of the box in React, where I had to write custom handlers to get dynamic image loading to work with some of the libraries in Vue. I do think that Vue is easier to learn as it is closer to traditional HTML and JS, which also makes it easy to read.

As I stated above, these are really just my first impressions and notes after a couple of days playing around with React, so I hope this does not seem like the blind leading the blind, but rather some simple connections between syntax and concepts that will help you get your first React project up and running, especially if migrating from Vue.