← Back to all snippets
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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs