React vs Vue: Programming Experience
After working with Vue for nearly an year, I recently moved to React. The experience working with both was quite different. While Vue was much simpler, React was more fun to work with.
There are ample articles that compare React and Vue on statistical basis (speed, size, support, etc.), so I would not touch those. I have added links to a few such articles at the end of this post. I would compare the two purely on coding experience point of view.
React: JSX is more intuitive
Mixing HTML and JavaScript has been a hot topic of discussion since the onset of React. Personally, I too wasn’t a big fan of this idea until I started working in React.
After I began using JSX, I felt it was easier and more intuitive — writing HTML logic right there in your code made it more natural to think and manage code.
HTML was not designed for logic, so putting directives like v-for
, v-if
, etc. is kind of a hack.
For example, look that the following Vue code where I have to render a placeholder row if there is no data in the table:
Compare this to React code:
What you can see is with JSX, we can use familiar constructs like, if statements, functions, loops, etc. which looks much more natural than Vue code.
Note: Vue also has added support for JSX: https://vuejs.org/v2/guide/render-function.html#JSX. However, its not that popular in Vue ecosystem.
React: One-Way data binding to the rescue
One of the most important factors, which is often ignored while comparing Vue (or Angular) and React, is — Vue has two-way data binding, while React has one-way data binding.
On the surface, two-way data bindings sounds better (and cooler), but more often than not — it results in unexpected behaviours and performance issues.
As aptly described by Jing Chen, creator of Flux, in this video:
With two-way data binding, there is just an explosion of command flows, and it is hard to tell if there is any infinite loop that might be causing a cascading effect.
For example, look that following Vue code:
I am trying to make a date-picker
component using an existing plugin. This code can result in an infinite loop because of two-way data binding:
- When I supply
2018–02–02
asvalue
to the component, it converts it into moment object and passes it to the date-picker. - Since, I updated the date-picker’s value, it’s update event gets fired.
- This results in component emitting the date again to update the model. However, this time updated date is something like:
2018–02–01T18:30:00+00:00
. Observe that this date is different from the date supplied. - Since, we got back a different date from the date-picker, we will end up updating the date again in the watcher, and thus resulting in an infinite loop.
This an actual component I had used in a project. However, I have removed all the extra conditions and checks I had to put in order to prevent an infinite-loop. Add to this the amount of time I had to spend debugging the code.
Update 1: With feedback from comments, I have added more explanation to this example, at the end of this article.
React: Better Code Management
In Vue, standard way to write components is using .vue
files, which combines HTML, CSS and JavaScript in same file.
In React, there is no such standard way. React components are regular JavaScript functions/classes and you can organise them the way you want.
Absence of a standard way provides freedom which leads to innovation. Paradigms such as Presentational and Container Components, and Styled Components, are a result of this.
Just imagine, you have a large application with hundreds of components — would you want to be restricted or be free to find the best way to organise your code?
One might argue that Vue is quite flexible too and
.vue
components are not a required way to write components. However, when you are dependent on community for support, other ways hardly matter. You would almost always go by the recommended way.
Vue: Easier to get started
Recently, I had to implement sorting of rows in an HTML table on the click of the table’s headers. I just included Vue.js on the page, attached it to the table element, implemented sorting in JavaScript, and Vue automatically rendered sorted table.
I could not have achieved this easily with React. Either I would have to write the React.createElement hell myself, or, setup a development environment with webpack to compile babel.
Conclusion
Personally, I find it more fun to work with React. With it, I can let my imagination run wild. Although Vue is much easier to get started and can be easily plugged into a part of a page, for bigger applications React is more suitable.
Update 1: The example given is not a direct example of two-way data-binding, rather of a component trying to implement it, i.e., trying to keep the v-model
, provided to the component, in sync.
In the example, consider the following usage of the component:
<DatePicker v-model="date" />
Here essentially, I want the date
variable to be in sync. That means:
- If I update
date
within the parent component (for example, I choose a start date for an event from a calendar plugin), I want the containeddate-picker
to update. - If I select a new date from
date-picker
, I want thedate
to get updated.
Following diagram will make it more clear:
Compare this to one-way data-binding flow in React:
While, this may also look like two-way flow, note that value from component to plugin is passed via value
prop, while from plugin to component via onChange
event. So, in our example:
- I provide
2018-02-02
as value. This, will be passed to plugin incomponentWillReceiveProps
and datepicker value will get updated. - Yes, this will fire the
dp.change
event which will fireonChange
event. - However, in
onChange
, we will not update thevalue
prop again which prevents circular loop.
Yes, this is also possible in Vue.
However, what I am trying to emphasise is that, in Vue, you expect components to be two-way binded. When working in a team, if you implement a different flow than this, it can lead to confusion and bugs.
Have a look at popular Vue plugins: vue-select, vue-slider, vue-datetime, etc. All of them are implemented with two-way binding using v-model.
Vue also has one-way binding
Yes, it does. However, if you look at documentation, and the intro video, you can see that most of the times two-way binding is used. Most of the developers would not know or use one-way binding in Vue.
For your reference, I add some other articles that compare React and Vue on statistical factors: