How to Create useLocalStorage Composable in Vue 3
Create a
useLocalStorage composable by defining a reactive state with ref and syncing it with localStorage using watch. Initialize the state from localStorage if available, and update localStorage whenever the state changes.Syntax
The useLocalStorage composable takes a key and an optional initialValue. It returns a reactive ref that stays in sync with localStorage.
key: The localStorage key to store the value.initialValue: The default value if nothing is stored yet.state: A reactive reference that updates localStorage on change.
javascript
import { ref, watch } from 'vue'; export function useLocalStorage(key, initialValue) { const storedValue = localStorage.getItem(key); const state = ref(storedValue ? JSON.parse(storedValue) : initialValue); watch(state, (newValue) => { localStorage.setItem(key, JSON.stringify(newValue)); }, { deep: true }); return state; }
Example
This example shows how to use useLocalStorage in a Vue component to keep a counter synced with localStorage. The counter value persists across page reloads.
vue
<template>
<div>
<p>Counter: {{ counter }}</p>
<button @click="counter++">Increment</button>
</div>
</template>
<script setup>
import { useLocalStorage } from './useLocalStorage';
const counter = useLocalStorage('my-counter', 0);
</script>Output
Counter: 0 (or last saved value)
[Increment button increments and saves counter]
Common Pitfalls
Common mistakes include:
- Not parsing JSON from
localStorage, causing string values instead of objects. - Not stringifying values before saving, which causes errors.
- Not watching deeply for nested object changes, so updates are missed.
- Using
localStoragedirectly without checking if it exists (e.g., in SSR).
javascript
/* Wrong: storing object without JSON.stringify */ localStorage.setItem('key', { count: 1 }); // stores '[object Object]' /* Right: use JSON.stringify and JSON.parse */ localStorage.setItem('key', JSON.stringify({ count: 1 })); const value = JSON.parse(localStorage.getItem('key'));
Quick Reference
- Use
refto create reactive state. - Initialize state from
localStoragewithJSON.parse. - Watch state changes and update
localStoragewithJSON.stringify. - Use
{ deep: true }inwatchfor nested objects. - Check for
localStorageavailability in non-browser environments.
Key Takeaways
Create a reactive ref initialized from localStorage using JSON.parse.
Use watch with deep option to sync changes back to localStorage as JSON strings.
Always stringify data before saving to localStorage and parse when reading.
Handle localStorage absence gracefully for server-side rendering or unsupported environments.
The useLocalStorage composable makes state persistence simple and reusable.