React vs Vue — Setting Attributes and Displaying Collections

John Au-Yeung - Jan 21 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

React has been 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 and has an incredibly passionate developer community adopting it.

It’s hard to choose between the 2 frameworks since they both have their pros and cons. When we choose one, we’ve to stick with it for a few years.

In this article, we’ll look compare the setting attribute and displaying collections with React and Vue.

Setting Attributes

With React, we can set attributes like HTML. But we can also set dynamic attributes in our app.

For example, we can write the following code to do that:

import React, { useState } from "react";

export default function App() {
  const [color, setColor] = useState("red");
  const toggleColor = () => {
    setColor(color === "red" ? "green" : "red");
  };

  return (
    <div className="App">
      <button onClick={toggleColor}>Toggle</button>
      <div className="box" style={{ color }}>
        foo
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we set the color of the div dynamically with the useState hook, which returns the setColor function to let us set the color.

Then we pass in the color to the style attribute. To set a static class name for our div, we have to use the className attribute. We have to remember differences like className instead of class when we set attributes with React.

With Vue, we put our data and methods in the component and set the static and dynamic attributes 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">
      <button @click="toggleColor">Toggle</button>
      <div class="box" :style="{color: color}">
        foo
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js:

const app = new Vue({
  el: "#app",
  data: {
    color: "red"
  },
  methods: {
    toggleColor() {
      this.color = this.color === "red" ? "green" : "red";
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

With Vue, we have to add the toggleColor method to the method and a default value for the color field in the data object.

Then we have to add the same logic for setting the color in the toggleColor method.

This is more complex than what we have with React. However, it does separate the logic for display and business logic into separate parts.

This is easier to deal with when our components are more complex.

Displaying Collections

We can display collections with React by mapping our arrays to a collection of components.

For example, if we have an array of names, we can write the following to display them with React:

import React, { useState } from "react";

export default function App() {
  const [persons] = useState([
    { name: "Mary" },
    { name: "John" },
    { name: "Joe" }
  ]);

  return (
    <div className="App">
      {persons.map(p => (
        <div>{p.name}</div>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the persons array, which is then mapped to divs with p.name as the text content.

To do the same thing with Vue, we can write the following:

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">
      <div v-for="p of persons">
        {{p.name}}
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js:

const app = new Vue({
  el: "#app",
  data: {
    persons: [{ name: "Mary" }, { name: "John" }, { name: "Joe" }]
  }
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the persons array in the Vue component, and the v-for directive to display items in the persons array.

This is cleaner than what we have with React. We keep the code in each file more compact.

This will be even more apparent is more components are more complex, which is often the case.

Another good thing about v-for is that we can use them to iterate through entries of an object as well.

For example, we can write the following to do that:

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">
      <div v-for="(age, name) in persons">
        {{name}}: {{age}}
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js:

const app = new Vue({
  el: "#app",
  data: {
    persons: {
      John: 20,
      Mary: 19,
      Jane: 20
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

We can get the value and key of an object’s entry respectively with:

v-for="(age, name) in persons"
Enter fullscreen mode Exit fullscreen mode

With React, we use Object.entries to do the same thing:

import React, { useState } from "react";

export default function App() {
  const [persons] = useState({
    John: 20,
    Mary: 19,
    Jane: 20
  });

  return (
    <div className="App">
      {Object.entries(persons).map(([name, age]) => (
        <div>
          {name}: {age}
        </div>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The expression is getting more complex since we have to call Object.entries and then map them to the component that we want to render.

Verdict

For simple components, there isn’t too much difference between React and Vue when it comes to setting attributes.

However, we do have to remember that they’re all camel case and the names might be different from HTML.

Vue has a slight edge here since we don’t have to worry about that. Dynamic attributes can be set with : and the rest is the same.

With Vue, we have to learn the v-for directive to render collections, while we just use plain JavaScript to do that with React.

However, with React, we have to write one big expression to do that, while in Vue, we can add directives to a template to do that.

This makes rendering collections cleaner with Vue, so Vue has the slight edge here as well.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .