npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mdus/use-localstorage-hook

v2.0.1

Published

React hook to manage localStorage state with sync, reactivity, and cross-tab updates.

Downloads

5

Readme

useLocalstorage

A React hook for safe, reactive access to localStorage, with:

  • Reactive state management with automatic re-renders
  • Cross-tab synchronization via storage events
  • Auto-initialization on mount with validation
  • Built-in set, get, remove, clearAll helpers
  • Support for any JSON-serializable data
  • Error-resilient design with comprehensive error handling
  • Zero dependencies — just native Web APIs + React

Why Use This Hook?

No more repeating localStorage.setItem logic in every component.

useLocalstorage is for React developers who want:

  • Reactive localStorage state that updates your UI automatically
  • Cross-tab synchronization - changes in one tab update others
  • One-liner setup of persistent browser state
  • Safety against stale keys or malformed data
  • Clean set/get/remove operations without spaghetti
  • Auto-persisted defaults on first load
  • Reusability across apps, components, and projects

Perfect for:

  • Auth tokens or user session keys
  • UI preferences (dark mode, language)
  • Cart data or product filters
  • Any local-only persistence logic that needs cross-tab sync

What Is This?

useLocalstorage() is a custom React hook that wraps the native localStorage API in a safe, reactive, composable way.

It handles:

  • Reactive state management with useState
  • Cross-tab synchronization with storage events
  • When to write to localStorage (useEffect)
  • How to write (with stringification and error handling)
  • Reading, removing, and clearing browser keys
  • Making it all memoized and safe for reuse

Installation

npm install @mdus/use-localstorage-hook
# or
yarn add @mdus/use-localstorage-hook

API Reference

What It Expects

| Argument | Type | Required | Description | | ------------- | -------- | -------- | ------------------------------------------------------- | | storeName | string | Yes | The key to use inside localStorage | | initialData | any | Yes | The default data to initialize if the key is empty/null |

What It Returns

| Key | Type | Description | | --------------- | ---------- | -------------------------------------------------------------- | | getStore | any | The current value from localStorage (reactive state) | | setStore | function | Sets a value into localStorage and updates the reactive state | | removeStore | function | Removes the item with this key from localStorage | | clearAllStore | function | Clears all localStorage entries |


Usage

1. Basic Reactive State

import useLocalstorage from "@mdus/use-localstorage-hook";

function ThemeToggle() {
  const { getStore: theme, setStore: setTheme } = useLocalstorage("theme", "light");

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    <div className={theme}>
      <p>Current theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}

2. Cross-Tab Synchronization

function UserPreferences() {
  const { getStore: prefs, setStore: setPrefs } = useLocalstorage("userPrefs", {
    language: "en",
    notifications: true
  });

  // This will automatically update across all open tabs
  const updateLanguage = (lang) => {
    setPrefs({ ...prefs, language: lang });
  };

  return (
    <div>
      <p>Language: {prefs.language}</p>
      <button onClick={() => updateLanguage("es")}>Switch to Spanish</button>
    </div>
  );
}

3. Managing Complex Data

function ShoppingCart() {
  const { getStore: cart, setStore: setCart, removeStore } = useLocalstorage("cart", []);

  const addItem = (item) => {
    setCart([...cart, item]);
  };

  const clearCart = () => {
    removeStore();
  };

  return (
    <div>
      <p>Items in cart: {cart.length}</p>
      <button onClick={() => addItem({ id: Date.now(), name: "Product" })}>
        Add Item
      </button>
      <button onClick={clearCart}>Clear Cart</button>
    </div>
  );
}

Key Features

1. Reactive State Management

The hook uses useState to provide reactive state that automatically re-renders your components when localStorage changes:

const [getStore, setGetStore] = useState(() => {
  try {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : initialData;
  } catch (err) {
    console.error(`Error reading localStorage key "${key}":`, err);
    localStorage.removeItem(key);
    return initialData;
  }
});

2. Cross-Tab Synchronization

The hook listens for storage events to keep multiple tabs in sync:

useEffect(() => {
  const handleStoreChange = (e) => {
    if (e.key === key) {
      try {
        if (e.newValue === null) {
          setGetStore(null);
        } else {
          setGetStore(JSON.parse(e.newValue));
        }
      } catch (err) {
        console.error(`Error parsing storage event for key "${key}":`, err);
        setGetStore(null);
      }
    }
  };

  window.addEventListener('storage', handleStoreChange);
  return () => window.removeEventListener('storage', handleStoreChange);
}, [key]);

3. Safe Initialization

The hook validates inputs and safely initializes localStorage:

if (!storeName || initialData === undefined) {
  throw new Error("useLocalstorage: storeName and initialData are required.");
}

4. Error Resilience

All operations are wrapped in try/catch blocks with meaningful error messages and fallback behavior.


Internals

Lifecycle-Safe Initialization

When the component mounts, the hook checks if localStorage already contains the key:

useEffect(() => {
  try {
    const existing = localStorage.getItem(key);
    if (existing === null) {
      setStore(initialData);
    }
  } catch (err) {
    console.error(`Error initializing localStorage key "${key}":`, err);
  }
}, [key, initialData, setStore]);

This prevents overwriting existing values.

Pure React API

  • Uses useState for reactive state management
  • Uses useCallback to memoize methods
  • Uses useEffect for storage event listeners and initialization
  • Safe to use inside other hooks and effects
  • Designed for composability in any React component

File Structure

use-localstorage-hook/
├── src/
│   └── useLocalstorage.js
├── dist/
│   └── index.js
├── package.json
└── README.md

Author

Md Umar Siddique


License

MIT © 2025 Md Umar Siddique


Final Note

This hook solves a real problem: managing persistent state in a clean, reactive, and React-friendly way with cross-tab synchronization. It reflects an engineering mindset focused on clarity, reusability, reactivity, and edge case safety — all in under 3KB of code.

If it saves you time, please consider starring and sharing.