JAVASCRIPT
Building a Reusable Composable for Local Storage Management
Create a custom Vue 3 Composition API composable to easily store and retrieve reactive state in `localStorage`, simplifying data persistence across browser sessions.
// useLocalStorage.js
import { ref, watchEffect } from 'vue';
export function useLocalStorage(key, defaultValue) {
const value = ref(defaultValue);
// Check if localStorage is available (for SSR compatibility)
const isBrowser = typeof window !== 'undefined' && window.localStorage;
if (isBrowser) {
// Load initial value from localStorage if available
const storedValue = localStorage.getItem(key);
if (storedValue !== null) {
try {
value.value = JSON.parse(storedValue);
} catch (e) {
console.error(`Error parsing localStorage key "${key}":`, e);
value.value = defaultValue;
}
} else if (defaultValue !== undefined) {
// If no stored value but a default is provided, store the default initially
localStorage.setItem(key, JSON.stringify(defaultValue));
}
}
// Watch for changes to 'value' ref and update localStorage
watchEffect(() => {
if (isBrowser && value.value !== undefined) {
try {
localStorage.setItem(key, JSON.stringify(value.value));
} catch (e) {
console.error(`Error saving to localStorage key "${key}":`, e);
}
}
});
return value;
}
// App.vue (Usage Example)
<template>
<div>
<h1>Local Storage Composable</h1>
<p>Saved Message: {{ message }}</p>
<input v-model="message" placeholder="Type a message to save" />
<p>Counter: {{ counter }}</p>
<button @click="counter++">Increment</button>
</div>
</template>
<script setup>
import { useLocalStorage } from './useLocalStorage';
const message = useLocalStorage('my-app-message', 'Hello Vue!');
const counter = useLocalStorage('my-app-counter', 0);
</script>
How it works: This snippet introduces a custom Vue 3 Composition API composable, `useLocalStorage`, designed to simplify data persistence in `localStorage`. It takes a `key` and an optional `defaultValue`. The composable initializes a `ref` with the value found in `localStorage` (or the default if none exists). It then uses `watchEffect` to automatically synchronize changes to the `ref` back into `localStorage`. This creates a reactive state that persists across browser sessions. The composable also includes basic error handling for JSON parsing and graceful fallback for non-browser environments, making it robust and easy to use across different components for various data types like strings, numbers, or objects.