Have you noticed my overly diplomatic title? It’s an attempt to frame this conversation in terms of what I prefer rather than what I believe to be objectively better in hope of diverting a flame war. I imagine it will not work.

React and Vue are ostensibly very similar and I have shipped projects using both. They both use a virtual DOM and they are both narrowly-focused view libraries. They are both solutions to the same problem as reactive HTML rendering tools but I believe they have a single defining difference that cascades down through your entire workflow. React fully embraces Javascript, Vue does not.

A common mantra often heard amongst React users is “it’s just Javascript” and that’s very true. Vue just seems to have a lot of unnecessary magic which makes components more difficult to reason about. Some examples:

Templates

A React component can be thought of simply as a function that returns elements (or at least a class with a function that does that). This functional approach is very natural to Javascript developers. Data in, elements out. If you have an array of things, you can simply map them to a list of elements. If you’d like to exclude some of those items, you can just use filter on the array and map the result to some elements. This functional workflow perfectly mirrors how you would reason about other parts of your application. This approach is complementary to Javascript’s strengths.

A Vue component is more like a template that can reference data from a data structure. It contains a DSL (Domain specific language) that, while minor, is completely unnecessary. I don’t need v-for because I have map(). I don’t need v-if because I have boring old regular if. Templates introduce at least some level of cognitive load for limited or no benefit.

Templates also introduce scoping issues. If I import some static data into my React component, I can use it in my render function because all the standard Javascript scoping rules apply. It’s just a function and behaves exactly as any other function would. Vue’s templates operate in a separate scope to the Javascript and so you have to incorporate that static data into your Vue component and return it as a computed field. None of these things are particularly painful but they are all unnecessary.

Tooling

Because React is “Just Javascript” the development experience is far better in my experience. For instance, prettier-js (An amazing, opinionated code formatter) just works on JSX but struggles with embedded expressions in Vue templates because Vue templates aren’t “Just Javascript”. Also, because the template and the Javascript operate in different scopes, it’s impossible (currently at least) for a linter to detect missing/misspelled variables in a template. Another minor irritation but it’s another unnecessary one.

The Deal Breaker: Mutable State

React and Redux embrace immutability at their core. In the same way that a React render function is a reducer that turns props into an element, React state changes are simply functions that reduce an old state and an action into a new state. Vue (and Vuex) however have a reactive state which means that you can modify the state in an imperative way. This doesn’t play well with the functional style that I use elsewhere in Javascript.

I’ve become very used to immutable data structures. They feel safe to me and Vuex pretty much forces you to not use them because of all the getter/setter magic that Vuex adds to the store. In React/Redux, the state/store are, you guessed it, “Just Javascript objects”

If you liked this article please remember to click the💚 symbol below to make sure more people get to read it!

Steven Poulton is a web developer and technical architect living in Manchester, England. In his spare time he likes to make indie music, make indie games and play with his indie cats.