JAVASCRIPT

Vue 3 useLocalStorageRef Composable

Create a custom Vue 3 `ref` that automatically synchronizes its value with browser's `localStorage`, providing reactive and persistent state management.

import { customRef } from 'vue';

function useLocalStorageRef(key, defaultValue) {
  let value = defaultValue;
  let storedValue;

  // Check if localStorage is available (client-side only)
  if (typeof window !== 'undefined' && window.localStorage) {
    try {
      storedValue = localStorage.getItem(key);
      if (storedValue !== null) {
        value = JSON.parse(storedValue);
      } else {
        localStorage.setItem(key, JSON.stringify(defaultValue));
      }
    } catch (e) {
      console.error('Error reading from localStorage:', e);
      // Fallback to default value if localStorage access fails
      value = defaultValue;
    }
  }

  return customRef((track, trigger) => {
    return {
      get() {
        track();
        return value;
      },
      set(newValue) {
        // Only update if the new value is different
        if (newValue !== value) {
          value = newValue;
          // Persist to localStorage
          if (typeof window !== 'undefined' && window.localStorage) {
            try {
              localStorage.setItem(key, JSON.stringify(newValue));
            } catch (e) {
              console.error('Error writing to localStorage:', e);
            }
          }
          trigger(); // Notify Vue to re-render
        }
      },
    };
  });
}

// Example Usage in a component:
// <script setup>
// import useLocalStorageRef from './composables/useLocalStorageRef';
// const userName = useLocalStorageRef('user_name', 'Guest');
// </script>
// <template>
//   <input v-model="userName" placeholder="Enter your name" />
//   <p>Hello, {{ userName }}!</p>
// </template>

export default useLocalStorageRef;
How it works: This `useLocalStorageRef` composable leverages Vue 3's `customRef` to create a reactive reference that automatically persists its value to `localStorage`. Upon initialization, it attempts to load the value from `localStorage`; if not found, it uses the provided `defaultValue`. Any subsequent changes to the ref's value are automatically saved, ensuring state persistence across page reloads. The `track` and `trigger` functions from `customRef` manage Vue's reactivity system, making the ref fully reactive like a standard `ref`.

Need help integrating this into your project?

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

Hire DigitalCodeLabs