React is the most popular front end library for the last few years.
Vue is a front end framework that’s catching up in popularity with React in the last few years.
It’s hard to choose between the 2 frameworks since they both their pros and cons. When we choose one, we’ve to stick with it for a few years.
In this article, we’ll compare how we can create React and Vue components, handle props and which one is more convenient for developers.
Creating Components
With React, we create components by creating a function, with the props passed in the props
parameter.
For example, we can create a component and pass a prop into it by writing the following code:
import React from "react";
function Foo({ msg }) {
return <div>{msg}</div>;
}
export default function App() {
return (
<div className="App">
<Foo msg="hello" />
</div>
);
}
In the code above, we created a Foo
component with a msg
prop that’s passed from App
to Foo
. Then we accessed the msg
property of the prop
parameter in the Foo
component and displayed msg
there.
With Vue, the way we define components and use them is similar to the React example.
We can create a Vue component and pass a prop into it as follows:
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Foo msg="hello"></Foo>
</div>
<script src="index.js"></script>
</body>
</html>
index.js
:
Vue.component("Foo", {
props: ["msg"],
template: "<div>{{msg}}</div>"
});
const app = new Vue({
el: "#app",
data: {}
});
In the code above, we created a Foo
component with Vue.component
, and then designate the msg
attribute as a prop.
Then in index.html
, we reference Foo
and pass in the msg
prop as we did with the React example.
As we can see, this simple example is pretty comparable between React and Vue.
Passing Data From Child to Parent
React and Vue both have the capability to pass data from child to parent.
With React, we can pass a function to a child component that takes some arguments.
The child calls the function so that the parent can get the data.
We can do what we described with React as follows:
import React, { useState } from "react";
function FooInput({ setMsg }) {
return <input onChange={e => setMsg(e.target.value)} />;
}
export default function App() {
const [msg, setMsg] = useState();
return (
<div className="App">
<FooInput setMsg={setMsg} />
<br />
<span>{msg}</span>
</div>
);
}
In the code above, we passed in the setMsg
function returned from the useState
hook to our FooInput
component.
Then FooInput
calls the setMsg
function which we passed in from the props with the value of the input.
This will then set the inputted value as the value of msg
.
Finally, we display the value of msg
in the span.
With Vue, we don’t have to pass in the parent’s functions directly into the child component.
Instead, we can emit an event with the value that we want to send to the parent. Then the parent can do whatever they want with the value.
We can do the same thing in our React example with Vue as follows:
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<foo-input v-bind:value="msg" v-on:input="msg = $event"></foo-input>
<br />
<span>{{msg}}</span>
</div>
<script src="index.js"></script>
</body>
</html>
index.js
:
Vue.component("foo-input", {
props: ["value"],
data() {
return {
msg: ""
};
},
watch: {
value(val) {
this.msg = val;
}
},
template: `<input v-model="msg" @input="$emit('input', $event.target.value)">`
});
const app = new Vue({
el: "#app",
data: {
msg: ""
}
});
In the code above, we have the foo-input
conponent, which takes a value
prop, which we set the latest value to this.msg
with the watcher so we aren’t mutating the value
prop directly.
Then we call $emit
with the input
event name and the entered value, which is stored in $event.target.value
.
The value entered is then sent to the parent and is available in the $event
object.
We listen to the event set the value to the msg
field by writing:
v-on:input="msg = $event"
as a directive on the foo-input
component.
We then display the value of msg
in the span below the foo-input
component.
Once we did all that, we should see what we typed in displayed below the input.
A shorthand for:
v-bind:value="msg" v-on:input="msg = $event"
is:
v-model='msg'
This is a special case and doesn’t apply to app emitted events.
So we can instead write:
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<foo-input v-model="msg"></foo-input>
<br />
<span>{{msg}}</span>
</div>
<script src="index.js"></script>
</body>
</html>
In any case, the React example is simpler. Passing data from child and parent components is definitely easier to React than Vue.
Verdict
The process for creating components and passing props from parent and child are pretty much the same when comparing React and Vue.
React does make passing data from child to parent easier than with Vue. We just pass in a function into the child and call it from there instead of emitting events and listening to them.