DEV Community

Vincent Tang
Vincent Tang

Posted on • Updated on

Learning Vue as a React Developer

React. The first major JavaScript framework I decided to learn coming from jQuery land.

My journey learning was painful. I had to watch three different Udemy tutorials to finally get it. Months were spent wrapping my head around this foreign way of coding.

I slowly and surely learned the basics, such how state management works and how the React lifecycle operates. These things came with time and eventually I learned to use this knowledge to build apps in hackathons and to build tools I would use in my daily life.

The time came to start my first development job as part of a team that used Vue. I didn't know anything about this framework and I felt like I had to learn JavaScript all over again.

This intense but interesting new journey where I transitioned from React to Vue left me with the following valuable lessons that I want to share with you.

Installation

Vue has a CLI like Create-React-App, but gives you more control with what settings you get out of the box. For instance, you can choose whether you want to include client-side routing or CSS Pre-processors like Sass.

Styling and Syntax

React uses JSX which lets you write HTML-like syntax.

Writing in Vue was like revisiting the good old days of EJS or any templating language. No longer did I have to write my HTML, and then convert it to JSX. I could just write HTML^TM and be on my way.

Here's an example of what a typical Vue file looks like:

<template>
  <div>
    <h1>{{message}}</h1>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: "Hello World"
      }
    },
  }
</script>

<style lang="scss" scoped>
  .h1 {
    color: red;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

Assuming you declared your Vue component at the top level, this just outputs a "Hello World" string in red color.

In Vue, you write single file components. By convention, your component file will include the declaration of your template at the top, followed by a script definition with all the component logic, and it wii close with any necessary style declarations.

React, on the other hand, is less opinionated on file structure. You can still create single file components but instead of implementing the template in HTML and the styling in SCSS, for example, you would write everything in Javascript: template in JSX and styling in CSS-in-JS. This is demonstrated in this example:

import React, { Component } from 'react';

export default class MyFirstComponent extends Component {
  state = {
    message: 'Hello World',
  };
  render() {
    return (
      <div>
        <h1 style={styles.color}>{this.state.message}</h1>
      </div>
    );
  }
}

// CSS in JS
const styles = {
  header: {
    color: 'red',
  },
};
Enter fullscreen mode Exit fullscreen mode

but you could also just import a .css or .scss file as well. The problem you run into though when using an import, is you pollute the global namespace. As your app and your team grows, chances are high your developer co-worker might name a class the same as yours.

You could opt to use a library like styled-components. This gives you a Sass-like syntax to tightly couple your styles with your JSX.

React brings another set of issues. Do you use a functional component or stateful component? By default, it's better to use only what you need, but this means potentially more refactoring down the road. This doesn't factor in that you can use React Hooks now instead of class components.

Props, State

React has something called props, which is data loaded in from the parent component. And something called state, data intrinsic to that component.

Here's an example of just rendering a "Hello World" message:

// React Parent Component
import React, { Component } from 'react';
import Child from './Child';

export default class Parent extends Component {
  state = {
    message: 'Hello World',
  };
  render() {
    return (
      <div>
        <Child message={this.state.message} />
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode
// React Child Component
import React from 'react';

const Child = props => {
  return <div>{props.message}</div>;
};
export default Child;
Enter fullscreen mode Exit fullscreen mode

With Vue, the concepts were the same. But Vue prefers convention over configuration. Meaning, there are specific naming conventions. Child components declared in parent component are in camelCase. When the component is added to the HTML, the syntax is then kebab-case.

Example:

<!-- Vue Parent Component -->
<template>
  <div>
    <child-component :message="message"/>
  </div>
</template>

<script>
  import ChildComponent from './ChildComponent.vue';
  export default {
    data() {
      return {
        message: 'hello world',
      };
    },
    components: {
      ChildComponent,
    },
  };
</script>
Enter fullscreen mode Exit fullscreen mode
<!-- Vue Child Component -->
<template>
  <div>
    {{message}}
  </div>
</template>

<script>
  export default {
    props: {
      message: {
        type: String,
        default: undefined,
      },
    },
  };
</script>
Enter fullscreen mode Exit fullscreen mode

Vue requires you to declare a child component twice, once on import another on Components.

React differs in that there is one less step, you import the file then use it.

Type Enforcement

One thing I miss in static languages like C# or Java is type enforcement. Javascript is a dynamic scripting language. Meaning it doesn't care if a variable is a string, number, boolean, etc.

When you declare a string, you can always typecast it to a number after. This makes scaling large frontend apps difficult. Because you might not know what data type you're working with.

React natively solves this with PropTypes. Example in the <Child/> component we made earlier:

import React from 'react';
import PropTypes from 'prop-types';

const Child = props => {
  return <div>{props.message}</div>;
};

Child.propTypes = {
  message: PropTypes.string.isRequired,
};

export default Child;
Enter fullscreen mode Exit fullscreen mode

There are a few issues with propTypes in React

  • It's really easy to misspell
  • It's optional
  • You have to declare an import

Because of these reasons, I find myself forgetting to use propTypes. You could opt to use Typescript instead with React, but this just means more additional time configuring your setup.

Vue requires the declaration of props, and propTypes are in the same location. Inside your <script> tag where all the other logic lives

Example of a child component:

<template>
  <div>
    {{message}}
  </div>
</template>

<script>
  export default {
    props: {
      message: {
        type: String,
        default: undefined,
      },
    },
  };
</script>

<style lang="scss" scoped>
</style>
Enter fullscreen mode Exit fullscreen mode

This is a much better design overall and makes it so that Typescript is not necessary in Vue.

Data Reactivity

This was the concept that tripped me on Vue several times. In React, everything is reactive. Meaning you can add properties to objects, and React would call it's lifecycle when properties changed.

In Vue ... things don't work the same. In React, every time you modify state, you could pass a new entire state object.

Vue differed in that you mutated your state directly through methods. Because we're intrinsically adding side effects, you have to actually declare when new properties are being added to the object.

Namely using something called Vue.set().

A common example of when you would use this is if your loading data from the backend. And need to create new data to send back.

You also have to define a key value for components that have been iterated. React / Vue work the same way, it lets the library know what parts to rerender on data changes.

Watchers and Observables

I never quite understood design patterns that well. But the term "observable" finally made sense to me.

Vue has something called watchers. This lets you call a method every time a specific variable changes.

However, there's some caveats, because you could have watchers watching watchers. This causes circular referential issues.

The Vue docs warn against this. I myself have accidentally done this using inputs to watch over other inputs.

React's implementation of watchers is through the lifecycle method of componentDidUpdate. You select which items you wish to watch independently inside of here.

For the React Hooks implementation, useState is another implementation of an observable

Computed properties

This was a new concept to me, from the React world. In Vue, you can have variables that depend on other variables. Anytime a dependency changes, so does the computed property.

It seems useful at first, but computed properties are only good if you aren't modifying it at all directly.

When you start needing to, this is when you go away from computed properties entirely to the next item...

Methods

Methods in Vue worked the same as in React. These methods were called through event-directives that extend from HTML DOM events. Examples include putting @click events, or @input if a user typed text in an input field.

Methods are what you'll always fall back in Vue when computed properties and watchers don't fit your use-case.

Methods are like any function in javascript. The return statement is optional, you can just use it to mutate data in the background.

Asynchronous Gotchas

This is a gotcha that you find out later in Vue, and in React.
In React, there is a built-in method called setState(). When setState() gets called, it gets handled asynchronously in the background.

Vue is no different, you have a method called Vue.nextTick() that awaits the latest updated value to the data.

One lesson I learned is that it's best to set local variables within your methods, and only mutate data attributes as needed.

Templates

With Vue, there is something called templates. In your component, you have the ability to declare <template> slots. When that component gets called, you can inject HTML where those slots match.

This has been immensely useful when working in libraries. I could inject functionality as I saw fit, to get the feature I needed.

Templates do not get rendered as a <div> element in the DOM. React has a similar approach to templates called fragments, but the approach is limited to just the first element in your component.

Lifecycle methods

Lifecycle methods describe what components do during their lifetime.

Here are common ones you'll use in Vue:

  • mounted() - Similar to React's componentDidMount. This generally when making an Axios/fetch call to initialize data in your component from a backend.
  • updated() - Similar to React's componentDidUpdate. When you update data through your components, you want to send a POST request to your backend to keep things in sync
  • destroyed() - Similar to React's componentWillUnmount. You don't need to use this, but it helps clean up leftover event listeners.

Hooks

Hooks makes React an extremely powerful framework. No longer did you have to use redux for handling state, you could just use useState() instead. No longer did you have to deal with setState(), there were a slew of other new improved methods to use.

Vue has no equivalent to hooks, although there is an RFC at the time of writing this

Directives

Vue's built-in directives make development a breeze. You could create iterable directives right inside your HTML.

In React, this often meant making another component called "group(s)" and maybe one called "group".

Vue, you can just dump the v-for, v-if etc right inside your HTML. Your logic coherently just makes sense looking at it.

Alternatively, you can write your own directives! This lets you attach functionality to page if necessary, making it easier to develop faster

One great use case for startups is to develop a reporting system. If a user clicks on a feature that doesn't yet exist, you can add a popup modal saying "Sorry we're working hard on this new feature! Come back later". In the background, you can make Axios request to notify users really do want that feature.

Mixins

Some companies swear by these. It's a reusable code snippet library that can be implemented across multiple components. React out of the box does not have such a feature, you can alternatively use callback functions instead that are made globally available

Emitting Events

Props are passed from parent to child component, via one-way data binding. To handle business logic at the parent level, from the child component, you generally emit events.

With Vue, there are two different ways.

  1. You can pass a reference to the function from parent to child
  2. Emit an event from the child and capture the response in parent

Most applications generally use #2. Example from a button that triggers a method in the parent component

<!-- Parent Component -->
<template>
  <ChildComponent @event-emitted="_handleUpdatedEvent"/>
</template>

<script>
  import ChildComponent from './components/ChildComponent.vue';

  export default {
    components: {
      ChildComponent,
    },
    methods: {
      _handleUpdatedEvent(val) {
        console.log('Button was clicked');
      },
    },
  };
</script>
Enter fullscreen mode Exit fullscreen mode
<!-- Child Component -->
<template>
  <div class="hello">
    <button @click="$emit('event-emitted')">Click Me</button>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Global State Management

Vue's CLI comes with the ability to add Vuex out of the box.

In React you pass a new set of state using setState(), Redux only extends this through global dispatches/flux architecture.

In Vue, you mutate objects behind the scene. Vuex is no different but at the global level.

Vue natively ships with the ability to create a global event bus, which is similar to React's context API.

Final Thoughts

Learning Vue has been a great way to learn new programming paradigms.

Many principles in React translate over to Vue. There are a few things that differ, namely:

  • You don't replace your state, you mutate it which creates data reactivity and async gotchas.
  • New constructs. There are computed properties, watchers, and mixins that don't exist in React out of the box
  • You write HTML and styles the way you would traditionally in a regular HTML page.
  • PropTypes are optional in Vue and React, but Vue requires less effort to enforce.
  • Styling. In Vue you just write Sass or CSS, it's super easy compared to React.

These are some of the differences from React to Vue. Some things that are similar include:

  • Lifecycle methods
  • Props/State
  • Assigning keys to iterated items
  • Methods / functions
  • Passing events upward

Top comments (14)

Collapse
 
ftonato profile image
Ademílson F. Tonato

Hey there,

I liked your comparison, I think it's makes it easy for everyone to understand a little bit more about each framework :)

I have some additional comments, first two typos:

On your example of what a typical Vue file looks like, you have:

// code...
<style lang="scss" scoped>
  .h1 {
    color: red;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

There is a . (dot) left before h1 tag

On the react code where you explain about template in JSX and styling in CSS-in-JS, you have:

// code...
<div>
  <h1 style={styles.color}>{this.state.message}</h1>
</div>

// code...

// CSS in JS
const styles = {
  header: {
    color: 'red',
  },
};
Enter fullscreen mode Exit fullscreen mode

You need to change the style={styles.color} to style={styles.header}


It might make sense to add a note to the Watchers and Observables topic, as we have been available since Vue 2.6.0+, a new behaviour for Observables.

Finally, the part where we have:

Vue requires you to declare a child component twice, once on import another on Components.

Is important to know that you can change this behaviour using lazy load/async components imports:

<!-- Vue Parent Component -->
<template>
  <div>
    <child-component :message="message"/>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: 'hello world',
      };
    },
    components: {
      ChildComponent: () => import('./ChildComponent.vue'),
    },
  };
</script>
Enter fullscreen mode Exit fullscreen mode

Thanks again for this comparison 🚀

Collapse
 
thecyberronin profile image
Ronin

I've been doing React dev for a few years now. I attempted to learn Vue a few times in the past few months and I just can't. It's not that Vue is harder to understand or set up, I always revert to React because I can do it so much quicker and I know it'll at least be fairly optimized (With my webpack config setup, etc). I'm sure I can get the same performance doing similar things with Vue. Since I did React first, I keep going back to it! D:

Collapse
 
dinsmoredesign profile image
Derek D

I have the same feelings, just the other way around. Obviously, it's because we're both just more comfortable with the way we have been doing it 😋

Collapse
 
vincentntang profile image
Vincent Tang

I find styling components in React to be a much slower process than Vue, but this is just my personal experience :)

Collapse
 
laurieontech profile image
Laurie

Great write up! Though I'm not looking at the markdown source I think some of your react examples have weird highlighting because they're marked as javascript instead of jsx. Both are supported. Could be wrong, but figured I'd mention it.

Collapse
 
vincentntang profile image
Vincent Tang

Thanks for the note!

I changed the files to jsx it should be fixed now :)

Collapse
 
kp profile image
KP

Good article. I'm only familiar with Vue but this provided a nice overview of React.
So, I'm going the obvious question....Vue or React? :D

Collapse
 
vincentntang profile image
Vincent Tang

I personally like using Vue especially when it comes to styling, but React has better overall 3rd party library support. Recently I wanted to use a geo-data location library but the official doc examples were only in React.

Example: github.com/uber/deck.gl

Collapse
 
kp profile image
KP
Thread Thread
 
vincentntang profile image
Vincent Tang

But see that's the thing, the code sandbox link doesn't work there and the information on Vue integration is limited at best

Collapse
 
thejoezack profile image
Joe Zack

Wow, very thorough write up! Thank you!!

Collapse
 
aimeetacchi profile image
Aimee

Great Post really interesting hearing your views coming from react to Vue. I may be using Vue in the future and I've learnt React first too. So thanks for this. :)

Collapse
 
metammodern profile image
Buniamin Shabanov

No longer did I have to write my HTML, and then convert it to JSX.

YOU DID WHAT?!

Collapse
 
bopbopbbe profile image
Bopbopbob

Thanks! As a react developer that is starting new job where they use Vue… this was a very good cliff notes.