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 about State Management with Composition API)
Here is a brief comparison between React and Vue hooks
Basic Hooks
useState
React:
const [currentState, setCurrentState] = useState("");
Vue
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.
// 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)
useEffect
React:
useEffect(() => {
console.log(`${currentState}`);
});
Vue
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
<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
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
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
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.
Top comments (2)
Great post!!!
What a good and brief post! Thank you.