Rooks
HooksState Management

useLocalstorageState

Persists React state in localStorage and synchronizes matching hook instances.

About

useLocalstorageState reads a JSON value from localStorage, falls back to an initial value, and keeps hook instances using the same key synchronized within and across documents.

Examples

Basic example

import { useLocalstorageState } from "rooks";

export default function PersistentCounter() {
  const [count, setCount, remove] = useLocalstorageState("my-app:count", 0);

  return (
    <section>
      <p>Persistent count: {count}</p>
      <button type="button" onClick={() => setCount((value) => value + 1)}>
        Increment
      </button>
      <button type="button" onClick={remove}>
        Remove stored value
      </button>
    </section>
  );
}

Using a boolean value to toggle a sidebar

import { useLocalstorageState } from "rooks";

export default function App() {
  const [showSidebar, setShowSidebar] = useLocalstorageState(
    "my-app:showSidebar",
    false
  );

  return (
    <div className="App">
      {showSidebar ? <aside></aside> : null}
      <main>
        <button onClick={() => setShowSidebar(!showSidebar)}>
          Toggle sidebar
        </button>
      </main>
    </div>
  );
}

Parameters

ArgumentTypeDescriptionDefault
keystringRequired localStorage key
initialStateS | (() => S)Value or lazy initializer used when no stored value existsundefined

Return value

Returns an array of following items:

Return valueTypeDescription
valueSCurrent in-memory value
setDispatch<SetStateAction<S>>Resolves and persists a value, then broadcasts it
remove() => voidRemoves the stored item; it does not reset local state

Behavior and lifecycle

Values are JSON encoded. Changing key reloads that key before persistence. Custom document events synchronize hook instances in one document, while the browser storage event synchronizes other same-origin documents; synchronized updates are not written back in a loop. Listeners are replaced when the key changes and removed on unmount. Rapid functional setters resolve against a ref holding the latest value.

Setting undefined removes the storage entry and leaves the in-memory value as undefined. Calling remove() only deletes storage; it does not update or broadcast the current value. Storage and serialization failures are logged, while the in-memory update continues.

Compatibility and accessibility

On the server, storage is unavailable and the initial value is returned. A stored client value can therefore differ during hydration; defer storage-dependent UI or use a client boundary when the markup can change. localStorage may be disabled by privacy settings and only supports JSON-serializable data. See SSR and browser APIs.

On this page