Vue Composition API and React Hooks comparison
Tags: vue3, hooks, react, vue
Published: 2020-10-26 11:36:37

With the release of Vue 3 we can now make use of the new Composition API, a set of additive, function-based APIs that allow flexible composition of component logic.

Using Composition API will give you multiple benefits like extraction and reuse of logic between components, Typescript support, local and global state management (you can read more [here](https://vueschool.io/articles/vuejs-tutorials/state-management-with-composition-api/) about State Management with Composition API)

Here is a brief comparison between React and Vue hooks

##Basic Hooks
### useState
React:
```javascript
const [currentState, setCurrentState] = useState("");
```

Vue
```javascript
const currentState = ref("");
```

With Vue 3 we have `ref` (used for primitives) and `reactive` (used for objects). Vue creates a reactive object  where we can set/get the value.

```javascript
// to set a value
currentState.value = "New value"

// to read the value
currentState.value
```

It is also possible to share the state with other components using `provide` and `inject` (more info [here](https://v3.vuejs.org/guide/component-provide-inject.html))

### useEffect
React:
```javascript
useEffect(() => {
 console.log(`${currentState}`);
});
```

Vue
```javascript
watchEffect(() => console.log(currentState))

// or watch
watch(currentState, (currentState, prevCurrentState) => {
  console.log(currentState, prevCurrentState)
})

```
Vue 3 introduces `watchEffect`, useful when you want to keep track of multiple source changes and when you don't need to know the old values. 
You can also use `watch` to track a single source lazily. The main difference between the two is that `watchEffect` runs immediately  while `watch` runs lazily. 
`watchEffect` also doesn't require separating the watched data source and the side effect callback.

##Computed and useMemo
In Vue 3, `computed` is a function that returns a reactive value based on one or more reactive sources. It can be used to derive a new value from existing reactive data without triggering unnecessary re-renders. When any of the reactive sources change, the computed value is automatically updated.

In React, `useMemo` is a hook that takes a function and an array of dependencies, and returns a memoized value that is only recalculated when one of the dependencies changes. It can be used to improve the performance of a component by avoiding expensive calculations on every render.

Vue
```javascript
<template>
  <div>
    <p>Sum of all numbers: {{ sum }}</p>
    <p>Numbers greater than {{ threshold }}:</p>
    <ul>
      <li v-for="num in filteredNumbers" :key="num">{{ num }}</li>
    </ul>
    <input type="number" v-model.number="threshold" />
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const numbers = ref([1, 2, 3, 4, 5]);
const threshold = ref(3);

const sum = computed(() => {
  return numbers.value.reduce((acc, num) => acc + num, 0);
});

const filteredNumbers = computed(() => {
  return numbers.value.filter(num => num > threshold.value);
});
</script>
```

React
```javascript
import { useState, useMemo } from 'react';

function NumberList({ numbers }) {
  const [threshold, setThreshold] = useState(10);

  const sum = useMemo(() => {
    return numbers.reduce((acc, num) => acc + num, 0);
  }, [numbers]);

  const filteredNumbers = useMemo(() => {
    return numbers.filter(num => num > threshold);
  }, [numbers, threshold]);

  return (
    <div>
      <p>Sum of all numbers: {sum}</p>
      <p>Numbers greater than {threshold}:</p>
      <ul>
        {filteredNumbers.map(num => <li key={num}>{num}</li>)}
      </ul>
      <input type="number" value={threshold} onChange={e => setThreshold(parseInt(e.target.value))} />
    </div>
  );
}
```

##Custom Hooks / Extraction and Reuse of logic
We can easily create custom hooks. Here is an example of a function returning the mouse position

React
```javascript
import { useEffect, useState } from "react";

export const useMousePosition = () => {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    const update = e => setPosition({ x: e.clientX, y: e.clientY });
    window.addEventListener("mousemove", update);

    return () => {
      window.removeEventListener("mousemove", update);
    };
  }, []);

  return position;
};
```

Vue
```javascript
import { ref, onMounted, onUnmounted } from 'vue'

export function useMousePosition() {
  const x = ref(0)
  const y = ref(0)

  function update(e) {
    x.value = e.pageX
    y.value = e.pageY
  }

  onMounted(() => {
    window.addEventListener('mousemove', update)
  })

  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })

  return { x, y }
}
```

That's all for now! I will try to keep updated this post with new examples.