React vs Vue — Handling Selections

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 is the most popular front end library for the last few years. Vue is a front end framework that’s catching up quickly.

It’s hard to choose between the 2 frameworks since they both have their pros and cons.

In this article, we’ll compare how React and Vue frameworks handle form radio button and drop-down selections and which one is easier for developers.

Radio Buttons

With Vue, we can use the v-model directive to bind the radio button choices to the component’s model directly.

For example, with Vue, we write the following to add a set of radio buttons and display the selected choice on the screen:

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">
      <input type="radio" value="One" v-model="picked" />
      <label>One</label>
      <br />
      <input type="radio" value="Two" v-model="picked" />
      <label>Two</label>
      <br />
      <span>Picked: {{ picked }}</span>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js :

const app = new Vue({
  el: "#app",
  data: {
    picked: ""
  }
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we just set the value of v-model of both radio buttons to the same picked model.

Then when we click either radio button, we’ll see the selected choice show in the span.

With React, we have to add the checked prop to each radio button so that only the value that’s selected is checked.

For instance, we write the following to rewrite the example above with React:

import React, { useState } from "react";

export default function App() {
  const [picked, setPicked] = useState("");
  const handleClick = e => setPicked(e.target.value);

  return (
    <div className="App">
      <input
        type="radio"
        value="One"
        checked={picked === "One"}
        onClick={handleClick}
      />
      <label>One</label>
      <br />
      <input
        type="radio"
        value="Two"
        checked={picked === "Two"}
        onClick={handleClick}
      />
      <label>Two</label>
      <br />
      <span>Picked: {picked}</span>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the same 2 radio buttons as in the Vue example, but we added a onClick handler to set the picked state, and we also have the checked attribute to indicate when they should be checked.

We indicate that we only want them selected when the given value is picked.

This is extra work that we don’t have to with Vue.

Handling Drop-Down Selections

We can use v-model to bind directly to the selected value of the dropdown with Vue.

Therefore, we can write the following to create a drop-down and then display the selected choice:

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">
      <select v-model="picked">
        <option>One</option>
        <option>Two</option>
      </select>
      <br />
      <span>Picked: {{ picked }}</span>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js :

const app = new Vue({
  el: "#app",
  data: {
    picked: ""
  }
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we created a dropdown and then bind the selected value to the picked model in the Vue component.

Then we referenced picked to display the selected choice in the span.

We didn’t have to specify the value if the value and the displayed text are the same.

With React, we write the following code to handle setting the selected value from a dropdown:

import React, { useState } from "react";

export default function App() {
  const [picked, setPicked] = useState("");

  return (
    <div className="App">
      <select onChange={e => setPicked(e.target.value)}>
        <option>One</option>
        <option>Two</option>
      </select>
      <br />
      <span>Picked: {picked}</span>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

To handle change in the value of a dropdown, we pass in an event handler to set the selected value to the picked state.

Then we display it in the span below the dropdown.

The Vue and React examples are pretty close with respect to handling dropdowns.

Multiple Selections

With Vue, it’s easy to handle the values of select elements that let users select multiple values.

We can write the following code 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">
      <select v-model="picked" multiple>
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
      </select>
      <br />
      <span>Picked: {{ picked }}</span>
    </div>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js :

const app = new Vue({
  el: "#app",
  data: {
    picked: []
  }
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we have a select element with the multiple attribute to enable multiple selection.

Then we just bind to the picked array with v-model and reference the picked array straight in the template to display the selected choices.

With React, we have to write the following to get the selected choices and display them:

import React, { useState } from "react";

export default function App() {
  const [picked, setPicked] = useState([]);

  return (
    <div className="App">
      <select
        multiple
        onChange={e =>
          setPicked([...e.target.selectedOptions].map(o => o.value))
        }
      >
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
      </select>
      <br />
      <span>Picked: {picked.join(", ")}</span>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the code, we reference:

[...e.target.selectedOptions].map(o => o.value)
Enter fullscreen mode Exit fullscreen mode

to get the selected options from the select element and then get the value property of each entry and put them in the picked array.

Then we display the picked entries by call join to combine the choices into one string.

As we can see, we have to do lots of things that we didn’t have to do in the Vue example to get equivalent functionality.

There’s way more logic involved just to get the selections from a select element that lets the user choose multiple choices.

Also, we have to spread the e.target.selectedOptions object so that we convert it to an array. e.target.selectedOptions is an array-like object, which isn’t an array.

Verdict

Vue is definitely better with handling radio buttons and select elements that let us choose multiple choices.

The v-model directive took care of most of the hard work of extracting the selected choices and displaying the data.

With React, we have to write our own code to extract the selected choices and display them also takes some work.

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