Vue Composition API vs. React Hooks

Suresh Mohan - Jul 21 '22 - - Dev Community

React Hooks were introduced with the React 16.8 update, and since then, they have become a necessity for single-page applications. They are a function type that allows you to hook into React state and lifecycle methods.

With the introduction of the Vue 3 update, Vue.js has challenged React with its new Composition API, which can extract pieces of reactive logic and share the code with other components.

This article will compare the Vue Composition API and React Hooks to help you understand the differences and similarities between them.

Way of Rendering

React Hooks are only featured in React functional components. These functional components execute with every rerender.

The following code example demonstrates how to use React Hooks. Initially, import the useState and useEffect Hooks from React. Next, use the useState Hook to add a local state inside the React functional component. Finally, use the changing function of useState to increment the value of the count with the help of the button onClick event. This useEffect runs on every render and will update the document title with its current value.

import React, { useState, useEffect } from 'react';

function Example() {

const [count, setCount] = useState(0);
 useEffect(() => {  
    document.title = You clicked ${count} times ; 
 });

return (
  <div><p>You clicked {count} times</p>
   <button onClick={() => setCount(count + 1)}>
     Click me
   </button>
  </div>
);

/**
 * when you click 10 times,
 * document title and paragraph will be displayed as "You clicked 10 times."
 */

}

export default Example;
Enter fullscreen mode Exit fullscreen mode

Way of rendering in React HooksIn Vue 3, a component is an object, and it can be defined with the setup() method introduced with the Composition API. You may feel that the React functional component’s body and Vue’s setup() operation work similarly. But the setup() method is only executed once, and it acts as an entry point to the Composition API. With the help of that, we can define a state, and this avoids recreating the state with every call.

The following code example shows only the script part of the Vue component. On top of it, we imported watchEffect and ref to define a variable and keep track of it. Inside the setup component, the price is defined with an initial value. The console log will give the updated value every time the price changes.

<script>
 import { watchEffect, ref, defineComponent } from "vue"; 
 export default defineComponent({ 
   name: "Store",
   setup() { 
    const price = ref(10); 
    watchEffect(() => console.log(price.value)); 
    return { 
     price 
    }; 
   },
 });
</script>

<template>
  <h3>Price</h3>
  <input v-model="price" id="price" placeholder="edit me">
</template>
Enter fullscreen mode Exit fullscreen mode

Way of Rendering price valueReactive Objects

useState is famous among the React Hooks and helps us to claim reactive objects. A two-member array represents the React useState , the first being the current value and the second being the function that can change the value.

function Example() { 

  const [count, setCount] = useState(0);
  return ( 
    <div>
       <p>You clicked {count} times</p>
       <button onClick={() => setCount(count + 1)}>
         Click me
       </button>
    </div> 
  );

}
Enter fullscreen mode Exit fullscreen mode

You can define the reactive object inside the new setup() component in the Vue Composition API. Unlike in React, you do not need to provide a mutation function (setCount) to change the value.

<template>
 <p>You clicked {{count}} times</p>
 <button @click="count += 1">
     Click me
 </button>
</template>

<script>
import { ref } from "vue";

export default {
  name: "Hooks",
  setup() {
    let count = ref(0);
    return {
     count,
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Implementing Reactive Objects

React has defined some rules for utilizing Hooks:

  • Hooks must be called on the top level of React function components.
  • Hooks should not be called inside loops, conditions, or nested functions.

Although these rules prevent issues like changing the order of Hooks execution by calling Hooks inside conditional blocks, the default behavior of setup() in Vue will prevent them, as it executes before the component is created.

Aesthetics and Readability

Defining the state

Vue draws more lines to perform the same functionality possible with a single line of React code. So yes, React Hooks is a valid choice for an elementary code like this. But when the code is complex, it will be easier to use the Vue Composition API than React Hooks. So, let’s add more variables and examine what looks better.

// React
const [name, setName = useState('Apple');
const [price, setPrice] = useState(20);
const [quantity, setQuantity] = useState(100);

// Vue
setup () {
  return {
     name: ref('Apple'),
     price: ref(20),
     quantity: ref(100)
  }
}
Enter fullscreen mode Exit fullscreen mode

So, it’s a win for Vue’s Composition API.

Changing the state

Let’s now see how to update the value of a variable. This comparison might be your decisive point in the battle between React Hooks and the Vue Composition API.

Inside the React function component, we defined a local state called name with its initial value, Apple. Then, we introduced an input element with an onChange event to change the value.

import { useState } from 'react'; 
function Example() { 
  const [name, setName] = useState('Apple');

  return ( 
    <form> 

     <input 
        type="text" 
        value=name 
        onChange={e => setName(e.target.value)} 
     /> 

     <h2>My favorite fruit is {name}</h2> 
    </form> 
  )
}
Enter fullscreen mode Exit fullscreen mode

Even though React tries to use native JavaScript whenever possible, Vue has new syntaxes like v-model making the code look pretty. The following example shows how we change the value of the local state name by using an input field.

<script>
import {ref} from 'vue'export default { 
  setup(){ 
    return {  
      name: ref('Apple') 
    } 
  }
}
</script> 

<template> 
  <form> 
     <input type="text" v-model="name"/> 
     <h2>My favorite fruit is {{name}} </h2> 
  </form>
</template>
Enter fullscreen mode Exit fullscreen mode

The previous code example demonstrates how easily you can change a variable with Vue. The main point is that the Vue code is more precise and readable. Such well-organized code will be handy when debugging.

Handling Side Effects

Examples of side effects include data fetching, setting up a subscription, and manual modification of the DOM. React attempts to handle side effects using the useEffect Hook.

The following useEffect Hook does not use any dependencies. With every render of the function, useEffect will be executed. It continuously updates the document title with the current value of the count state.

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
     document.title = `You clicked ${count} times`; 
 });

  return ( 
     <div>
       <p>You clicked {count} times</p>
       <button onClick={() => setCount(count + 1)}> 
          Click me 
       </button></div> 
  );
}
Enter fullscreen mode Exit fullscreen mode

The Composition API has two methods for dealing with side effects, watch and watchEffect. Nevertheless, they have their uses.

When multiple variables change, React’s useEffect allows the developer to keep track of these variables and activate a callback function. watchEffect is something we especially think of with Vue’s Composition API, but it does not keep track of the variable values. To achieve that, we have to use a watch().

The following example shows how to implement watchEffect. Whenever the price value changes, watchEffect will be executed and give the console log.

<script>
import { watchEffect, ref, defineComponent } from "vue";
export default defineComponent({ 
 setup() { 
   const price = ref(100); 
     watchEffect(() => 
       console.log(price.value)) 
   ); 
   return { 
     price 
   }; 
 },
});
</script>
Enter fullscreen mode Exit fullscreen mode

Key differences:

  • useEffect  — We can tell when the effects will be active by manually adding dependencies. useEffect should be called inside the component.
Case 01:
  useEffect(() => {
    //Runs on every render.
  });

  Case 02:
  useEffect(() => {
    //Runs only on the first render.
  }, []);

  Case 03:
  useEffect(() => {
    //Runs with first render OR whenever the dependency value changes.
  }, [prop, state]);
Enter fullscreen mode Exit fullscreen mode
  • watch— This works very similar to useEffect. We have to tell it when to run the callback function.
//The callback is called whenever `refA` changes.
  watch(refA, () => {
    console.log(refA.value);
  });
Enter fullscreen mode Exit fullscreen mode
  • watchEffect  — With this, we don’t need to add specific dependencies manually. It will run the callback function whenever the reactive variables we use inside it change. And watchEffect works outside of a Vue component.
//The callback is called immediately, and
  //whenever `refA` or `refB` changes ...
  watchEffect(() => {
    console.log(refA.value);
    console.log(refB.value);
  });
Enter fullscreen mode Exit fullscreen mode

Note: The main difference is that the watchEffect starts instantly while the watch() runs lazily.

Final Thoughts

The basis for everything we discussed throughout this article is JavaScript. So first, we went through the React Hooks and alternatives provided by Vue Composition API.

React does not attempt to deviate much of its code from Vanilla JavaScript. And Vue uses fewer lines of code and less time to perform the same operation that React Hooks does. We realized that the Vue code is more precise and readable, which means it has a higher maintenance capability. If you intend to switch from one to the other or are in the stage of choosing between React and Vue, I hope this article gives you a few insights. Thank you for reading!

The Syncfusion React suite offers over 70 high-performance, lightweight, modular, and responsive UI components in a single package.

The Syncfusion Vue UI components library is the only suite you will ever need to build an app. It contains over 65 high-performance, lightweight, modular, and responsive UI components in one package.

For questions, you can contact us through our support forum, support portal, or feedback portal. We are always happy to assist you!

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