Edit (31 July 2023): Some of this is now outdated, especially how to scaffold and run Vue/React projects. Vue CLI and create-react-app are no longer the preferred tools. Instead, Vite has taken both their place. Vue has since also also introduced Vue 3 and together with it, the powerful composition API, but any Vue code in this article is valid Vue 3 code as well.
You're probably here because you're a VueJS developer, and you've recently switched jobs, and your new workplace uses React, or your current boss wants a project done in React, or maybe because you want to learn it yourself. I am happy to tell you that you've managed to find the right article for it (just curious though, how did you find this post? Could you leave a comment below?). Vue was the first single-page application library I took on. Even coming from a non-ES6 background, it was easy to learn, and I quickly learned the joys of component-based coding. After I had found some amount of comfort with Vue, I decided to learn React, and loved it instantly as well. The good news is, once you've learned one library that employs component-based architecture, it's not very difficult to migrate to others that do the same.
At the time of writing, I envision this to be the first of four parts. The first part, this one, will deal with the basics. In the second part, we'll go over some more common tasks we face while coding SPAs, like displaying lists. The next part will talk about router and navigation, and the final part will go into making our own custom components.
Before I begin, though, I will have to make a few assumptions -
- You use the command-line/terminal tools for generating Vue and React projects. So, you should be using Vue Cli and create-react-app. Instructions on how to use them to create projects are on their websites (which I have linked here).
- You're familiar, for the most part, with ES6 syntaxes and concepts, mostly modules, exports, imports, and classes; also arrow functions.
Modules, classes, and functions
First, understand the similarity between Vue and React. Both deal with components - reusable sections of code which can be plugged into other sections, almost behaving like HTML tags. They both have an "entry point", which is typically named App.vue or App.js. The way they treat components is different though - components are module-based in Vue, and class or function based in React. This is how you would write a typical 'Hello World' component in Vue :
<!--App.vue-->
<template>
<div>
Hello World!
</div>
</template>
<script>
export default {
//stuffs and things
}
</script>
And here is the React (function component) equivalent
//App.js
import React from 'react'
function App() {
return (
<div>
Hello World!
</div>
)
}
export default App;
Written as an arrow function (which I personally prefer) it would look like
//App.js
const App = () => (
<div>
Hello World!
</div>
)
React is written in JSX, which is a language that looks very similar to HTML in tags, with the power of JavaScript built in. What your component does is, it returns a JSX (a combination of layout and JavaScript codes) that is rendered as a React element in the appropriate place on the screen.
While React allows both class and function components, the latter results in much cleaner and more readable code. Function components used to have the disadvantage of being stateless, but that has been mitigated with React hooks (explained below). This post will focus solely on function components. Maybe I'll edit this post someday to include class components, when I have more time.
State
State is the, well, state the component is in. Typically this means a collection of key-value pairs, which determine the values displayed in various parts of the page, or properties certain elements take on. In Vue, we keep state inside the data
function. An example would be the following -
<!--template code above this, omitted for clarity-->
<script>
export default {
data() {
return {
name: "",
loadComplete: false
}
}
}
</script>
Prior to October 2018, only class components in React could have their own state. However, at React Conf, the developers introduced something really useful called "React Hooks". You are perhaps aware of lifecycle hooks in Vue (mounted
, updated
, etc.). React hooks work in a similar way, but also help us include state in function components. For this, we'll need to use a hook called useState
. This is how the same Vue component as described above would translate into a React function component.
import React, {useState} from 'react'
const App = () => {
const [name, setName] = useState("");
const [loadComplete, setLoadComplete] = useState(false);
return (
{/* JSX here */}
{/* btw, this is also how you put a comment inside JSX */}
)
}
As you can see above, React makes use of the destructuring syntax to identify an immutable state key, and a function to set its value. The argument you pass into useState
is the initial value that this key should hold. For example, in case of loadComplete
, its initial value is false
. (Examples of how to set and get these state values are right down below)
Let's start at the very beginning, a very good place to start...
In most applications, what you're looking for is a way to fire off a set of instructions whenever the page loads for the first time. Typically, you would be calling an API and getting data from it in this section. In Vue, the method mounted
is your friend in this regard. An example of how you would call an API and populate state might look like this.
export default {
data() {
return { name: "" }
},
mounted() {
fetch('http://some.api')
.then(r => r.json())
.then(res => { this.name = res.data.name });
}
}
There is an argument that server data should never be stored in state, but rather in a server cache. I've read a few articles about it, and they make good points, but for the sake of simplicity I'm just using state here.
In order to do the same in React, we're once again gonna use, you guessed it, hooks. We'll need the useState
hook, of course, but we'll also make use of another hook called useEffect
. This is a function that takes (optionally) multiple arguments, the first of which is a function block (usually an anonymous one) which fires immediately when the page loads or renders.
import React, {useState, useEffect} from 'react'
const App = () => {
const [name, setName] = useState("");
useEffect(() => {
fetch('http://some.api')
.then(r => r.json())
.then(res => { setName(res.data.name) });
});
return (
{/* JSX here */}
)
}
(Don't try to set the value of name
directly. It is immutable and should be treated as such.)
The code above is mostly fine, with one problem. This would fire not only the first time, but literally every time anything triggers a render in the page (useEffect
, in essence, encompasses the functionalities of both mounted
and updated
in Vue). In order to make sure this fires once and only once in the very beginning, we have to pass it a second argument. This second argument contains a list of states to watch out for. As such, the function defined as the first argument of useEffect
will only fire when any of these states have changed values. We'll pass a blank array as this argument. This tells React this is a "fire and forget" execution. The modified code will look like
useEffect(() => {
fetch('http://some.api')
.then(r => r.json())
.then(res => { setName(res.data.name) });
}, []);
Displaying state values
This one's pretty straightforward, so I'll jump right in and just show you the code fragments. They contain two examples each - first, how to display plain text somewhere on the web page, and the other, displaying dynamic text inside a text box. Should be self-explanatory.
Vue:
<template>
<div>
<h3>Name:</h3>
<div>{{ name }}</div>
<input type="text" :value="name" />
</div>
</template>
<script>
export default {
data() {
return { name: "" }
}
}
</script>
React:
const App = () => {
const [name, setName] = useState("");
//fetch and set name
return (
<div>
<h3>Name:</h3>
<div>{ name }</div>
<input type="text" value={ name } />
</div>
)
}
There is no equivalent for v-model in React. React does not support two-way binding.
Event Binding
The examples above already show how to bind state values to elements. Let's look at how we can bind events to their respective event handlers. In Vue JS, you would have written a method inside the "methods" section, and then bound it with an @event
directive, for example -
<template>
<div>
<button @click="btnClicked">Click Me</button>
</div>
</template>
<script>
export default {
methods: {
btnClicked() {
alert('Clicked!')
}
}
}
</script>
In React, there is no methods section, you just write your handler somewhere inside the component, and link it to the event using an anonymous arrow function.
const App = () => {
const btnClicked = () => alert('Clicked!');
return (
<div>
<button onClick={ () => btnClicked() } />
</div>
)
}
And I think I'll wrap up here for now. This barely scratched the surface, and I admit was reasonably fast-paced. But my goal was to just give a quick introduction to React to an experienced Vue developer, drawing parallels and explaining differences. I'm sure you can dig deeper and learn it better yourselves. And like they say, "There are some bugs coders can't fix, for everything else there's Stack Overflow..." okay I'll stop digressing. Hope you enjoyed this article, and I'll see y'all in the next one.
[To be continued]
Top comments (0)