Lesson 5 of 7
Composables
You will learn how to write composables: plain that use the Composition to share reactive logic between components. They are Vue's equivalent of React's custom hooks.
// composables/useFetch.js
import { ref, watchEffect, toValue } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
const loading = ref(false)
watchEffect(async () => {
const resolvedUrl = toValue(url) // works with ref or plain string
if (!resolvedUrl) return
data.value = null
error.value = null
loading.value = true
try {
const res = await fetch(resolvedUrl)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
data.value = await res.json()
} catch (e) {
error.value = e
} finally {
loading.value = false
}
})
return { data, error, loading }
}<!-- Using the composable -->
<template>
<div>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useFetch } from './composables/useFetch'
// Works with a static URL
const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts')
// Also works reactively — refetches when postId changes!
const postId = ref(1)
const { data: post } = useFetch(() => `https://jsonplaceholder.typicode.com/posts/${postId.value}`)
</script>
<!-- composables/useLocalStorage.js -->
<script>
import { ref, watch } from 'vue'
export function useLocalStorage(key, defaultValue) {
const stored = localStorage.getItem(key)
const value = ref(stored ? JSON.parse(stored) : defaultValue)
watch(value, (newVal) => {
localStorage.setItem(key, JSON.stringify(newVal))
}, { deep: true })
return value
}
</script>
<!-- Using useLocalStorage -->
<script setup>
import { useLocalStorage } from './composables/useLocalStorage'
const theme = useLocalStorage('theme', 'light')
const settings = useLocalStorage('settings', { notifications: true, lang: 'en' })
</script>Finished reading?Mark it done to track your progress.
Tip: use the ← and → keys to move between lessons.