DEV Community

Cover image for React vs Vue: my personal point of view
Giuseppe
Giuseppe

Posted on • Edited on

React vs Vue: my personal point of view

Being a Front End developer I've got the luck to have worked with both React and Vue. I have worked with React for almost one year (2017-2018) and I've been working with Vue since July 2018 (when I joined MotorK).

This post won't be about which could be the best between React and Vue, but it will be about my personal point of view. I don't write what I prefer at the end of the post, but I'm going to do it now; at the beginning.

My favourite one is ๐Ÿฅ๐Ÿฅ๐Ÿฅ Vue! And I'm going to explain to you why.

Table of Contents

  1. Separation of concerns
  2. No JSX
  3. Computed props
  4. Mixins
  5. Ecosystem

Separation of concerns

One of the best features of Vue is the "separation of concerns" of Single File Components (SFC). In Vue's SFC there are three available blocks: <template>, <script> and <style> whose the goal is to split the HTML, the JavaScript and CSS code.

So, what you could have in a SFC is something like:

<template>
    <section class="awesome-vue-component">
        <header class="awesome-vue-component__header">{{header}}</header>
        <div class="awesome-vue-component__body">{{body}}</div>
        <footer class="awesome-vue-component__header">{{footer}}</footer>
    </section>
</template>

<script>
    export default {
        name: 'AwesomeVueComponent',
        props: {
            header: {
                type: String,
                required: true,
            },
            body: {
                type: String,
                required: true,
            },
            footer: {
                type: String,
                required: true,
            },
        }
    }
</script>

<style lang="scss" scoped>
    .awesome-vue-component {
        &__header { 
            font-size: 18px;
        }

        &__body { 
            font-size: 14px;
        }

        &__footer { 
            font-size: 11px;
        }
    }
</style>
Enter fullscreen mode Exit fullscreen mode

The same code in React would be something like:

import "awesome-react-component.scss";

class AwesomeReactComponent extends React.Component {
    render() {
        const {
            header,
            body,
            footer
        } = this.props;

        return (
            <section className="awesome-vue-component">
                <header className="awesome-vue-component__header">{header}</header>
                <div className="awesome-vue-component__body">{body}</div>
                <footer className="awesome-vue-component__footer">{footer}</footer>
            </section>
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Since React doesn't support blocks, the only way to import SCSS is reading of an external .scss file, which adds a little bit of complexity to the component.


No JSX

As I've already shown you, React doesn't give you the possibility to write a well-easy understandable code. Since it doesn't have blocks, it must mix HTML and JavaScript. This "mixture" is called JSX which is a JavaScript's syntax extension for describing UI parts.

But why I don't like JSX?
Just let me give you one example:

Vue code

<template>
    <section class="posts">
        <section v-for="post in posts" :key="post.id" class="post">
            <header class="post__header">
                <h3 class="post__title">{{post.title}}</h3>
            </header>
            <div class="post__body">{{post.body}}</div>
            <footer class="post__footer">
                <p>{{post.footer}}</p>
            </footer>
        </section>
    </section>
</template>
Enter fullscreen mode Exit fullscreen mode

React code

class Posts extends React.Component {
    render() {
        return (
            const posts = this.props.posts.map( post => {
                return (
                    <section key={post.id} className="post">
                        <header className="post__header">
                            <h3 className="post__title">{post.title}</h3>
                        </header>
                        <div className="post__body">{post.body}</div>
                        <footer className="post__footer">
                            <p>{post.footer}</p>
                        </footer>
                    </section>
                )
            } );

            <section className="posts">
                {posts}
            </section>
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

I find the Vue's code more readable, clear and easy to understand.
I mean: it's just HTML code after all, isn't it?

Woah
I know, some of you are thinking: "Hey, you should create a Post component and put the code inside it!" And yes: you're totally right, but the focus of this point is that, using React, you must mix HTML and JavaScript code, which is something I really don't like because it could lead you in writing more bugs.


Computed props

Computed props are another nice Vue's feature. Basically they're function whose the result is cached based on their reactive dependencies.

... WTF?!

Ok, let me explain it better.
Computed props are used for wrapping a piece of logic that depends on a reactive data (props or data) and they are (re)evaluated only if their reactive dependencies change.

Let me give you a real example:

<template>
    <div class="dummy-vue-component">
        <p>{{greetByMethod()}}</p>
        <p>{{greetByComputed}}</p>
    </div>
</template>

<script>
    export default {
        name: 'DummyComponent',
        props: {
            name: {
                type: String,
                required: true,
            }
        },
        methods: {
            greetByMethod() {
                return `Hello ${this.name}`;
            }
        },
        computed: {
            greetByComputed() {
                return `Hello ${this.name}`;
            }
        }
    }
</script>
Enter fullscreen mode Exit fullscreen mode

greetByMethod() and greetByComputed() will produce the same result, with an important difference: the first one is called everytime the UI gets a re-render, the second one is re-evaluated only if this.name changes. So, as you can easily understand, computed props are better and more performant.
You should use a method only if you need to pass a parameter from the view; otherwise go with a computed.

N.B. When you use computed props, you have to get rid of (), otherwise Vue will run them like methods and your app won't work anymore.


Mixins

Mixins allow you to share pieces of code (props, computed, methods and life-cycle methods) among components. Basically it consists in a JavaScript object to inject into a Vue's instance.

/**
 * @mixin InputMixin
 */
export const InputMixin = {
    data() {
        return {
            value: ''
        }
    },
    props: {
        id: {
            type: String,
            required: true,
        },
        name: {
            type: String,
            required: true,
        }
    },
    computed: {
        getUniqueKey() {
            return `${this.name}-${this.id}`
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This is a simple mixin which can be injected into a component in this way:

<template>
    <div class="input-text">
        <input
            v-model="value"
            :id="getUniqueKey" 
            :name="name" 
            type="text" />
    </div>
</template>

<script>
    import { InputMixin } from './base-mixin';

    /**
     * @mixes InputMixin
     */
    export default {
        name: 'InputText',
        mixins: [
            InputMixin
        ]
    }
</script>
Enter fullscreen mode Exit fullscreen mode

The InputText component will contain the whole base-mixin.js content: data, props and computed.

If you have a different component, which needs of same props, computed and data, you can use this mixin and avoid the code duplication. Cool, isn't it?

N.B. Since mixins add complexity to the component, you should use the @mixes JSDoc tag to indicate that the component is using a mixin.


Ecosystem

Another point in favor of Vue is its incredible Ecosystem.
I like to define Vue as "micro-framework" because it can be extended with other libraries like Vuex and Vue Router. These two libraries are maintained by Vue's core team and this is something that React doesn't have. Actually also React can be extended installing Redux and React Router, but they are projects not managed by the React team which means they are unofficial.
This possibility shouldn't be either ignored nor underrated, because having a libraries handled by the same team it's really important to have a more stable application.


Follow me on

If you liked the post, you might offer me a โ˜•๏ธ on PayPal. ๐Ÿ™‚


Top comments (7)

Collapse
 
ngacho profile image
Ngacho

I'm seated here wondering how I can React to to your personal point of Vue.

Collapse
 
ghost profile image
Ghost

The pun gods are pleased.

Collapse
 
oskarkaminski profile image
Oskar • Edited

Giuseppe,

I like the way you presented the differences BUT...
I tend to feel your opinion may be a bit to single dimensional - each of the frameworks took a tradeoff that would be good to mention.

For example the sample code for React

import "awesome-react-component.scss";

class AwesomeReactComponent extends React.Component {
    render() {
        const {
            header,
            body,
            footer
        } = this.props;

        return (
            <section className="awesome-vue-component">
                <header className="awesome-vue-component__header">{header}</header>
                <div className="awesome-vue-component__body">{body}</div>
                <footer className="awesome-vue-component__footer">{footer}</footer>
            </section>
        );
    }
}

Should be rather built in a shorter, easier form:

import "awesome-react-component.scss"

const AwesomeReactComponent = ({header, body, footer}) => (
  <section className="awesome-vue-component">
    <header className="awesome-vue-component__header">{header}</header>
      <div className="awesome-vue-component__body">{body}</div>
      <footer className="awesome-vue-component__footer">{footer}</footer>
  </section>        
)

Then you could say, that in return to less clear separation of concerns, React code can be way more concise without that much of the boilerplate.

Collapse
 
sanfra1407 profile image
Giuseppe • Edited

Hi Oskar,
thank you for your comment.

Yes, you can write that component in that shorter way but:
1) The component you've written it's a "functional component" which something different from the one I wrote;
2) You're still mixing the JavaScript and the HTML, because basically you're putting HTML in a const;

P.S My name is Giuseppe ๐Ÿ˜ฌ

Collapse
 
oskarkaminski profile image
Oskar • Edited

Sorry for misspelling your name :(

Don't you think we should compare functional components instead of class components since they are officially recommended way to build components in React ?

Technically those component's are not a mix of HTML and JS. It's a pure JS with a small library, that enables us to write JS object trees in HTML-like way. But I agree, that ability to mix logic and JSX often results in overuse and messy code build by inexperienced developers.

Collapse
 
oskarkaminski profile image
Oskar

Guiseppe,

I appreciate your preference in having state management and routing managed by the same team BUT...

I'm afraid, that doing so was a common mistake over the years that is repeated over and over again.
The simple reason is, more tools the team must maintain, less time they have for each of them.

The Angular way of maintaining the whole ecosystem reminds me TV with VHS builtin era.

I think this is the reason why so many people moved from Angular to React recent years.

But there are situations where Angular way is a better one. I think if you work in corporate environment, and you need to vet every package you are using, it's easier to get approval on "batteries included" framework as Angular and go with it, that ask for Mobx, React-router, axios etc. separately.

Also for people who start coding, having a choice made for them can help.

Collapse
 
aisone profile image
Aaron Gong • Edited

I have used both in production on complex projects

React

1 infinite call to render if you do not handle re-render correctly

2 changes not rendered if you do not handle re-render correctly

3 unintended renders when parent updates

4 Not easy to debug / extend functionality of component/s of HOCs wrapped in many layers... e.g: populateTable(i18n(userFilter(getAuthGroup(getSomeData))

5 if a 3rd party HOC name clashes with another 3rd party HOC that you use... one will overwrite the other and you will get problems

Vue

1 directives (v-if, etc), but easy to get used to (some dislike directives as it seems like magic...)

2 slots are used instead of HOC, does not look as elegant as React.

3 this.abc below can cause problems...

props: ['abc'],
data () { return { abc: '' } }
methods: { abc () { } }

Own experience (your mileage may differ)

For the same project specs, I take half the time to complete using Vue because in React, I have to be more careful about direction of data flow, and re-render

This is because of the different way React and Vue updates the virtual DOM

In React when the parent updates, all the child and below updates unless you specify not to (in React Hooks, the [] in useEffect controls what gets updated)

In Vue reactivity in a component is specified in the "data" property

So far I have not seen the headaches of deeply nested React HOC wrapping in Vue, perhaps due to the way slot works

e.g. A has slot B, B has slot C... but C is not affected directly by A... Maybe because it is like this that makes it hard to run into problems...