State

useLocalStorageWithExpiry

Persisted state with a TTL.

Demo

stored value
expires in

nothing stored yet

Usage

use-local-storage-with-expiry.tsxtsx
import { useLocalStorageWithExpiry } from "hookli";

export function Demo() {
  const { value, setStoredValue } = useLocalStorageWithExpiry(
    "draft",
    "",
    10_000,
  );

  return (
    <div>
      <button onClick={() => setStoredValue("hello")}>Save for 10s</button>
      <p>{value === null ? "Expired" : value || "Nothing stored"}</p>
    </div>
  );
}

API

useLocalStorageWithExpiry.d.tsts
useLocalStorageWithExpiry<T>(key: string, initialValue: T, expiryMs: number): { value: T | null; setStoredValue: (value: T) => void }

Parameters

NameTypeDefaultDescription
keystringThe localStorage key to read and write.
initialValueTValue used before hydration and when nothing is stored under the key.
expiryMsnumberTime-to-live in milliseconds. Every write stores the value with a fresh expiry timestamp.

Returns

NameTypeDescription
valueT | nullThe stored value, or null once the item has expired. Expiry is checked when the hook reads — on mount or key change — at which point the item is removed.
setStoredValue(value: T) => voidPersists the value to localStorage with a new expiry of now + expiryMs.

Hook

The implementation, straight from hookli. Copy it, or install the package.

src/hooks/useLocalStorageWithExpiry.hook.tstsx
import { useEffect, useState } from "react";

export const useLocalStorageWithExpiry = <T>(
  key: string,
  initialValue: T,
  expiryMs: number,
) => {
  const read = (): T | null => {
    if (typeof window === "undefined") return initialValue;

    const raw = window.localStorage.getItem(key);
    if (!raw) return initialValue;

    try {
      const item = JSON.parse(raw);
      if (
        item &&
        typeof item.expiry === "number" &&
        Date.now() > item.expiry
      ) {
        window.localStorage.removeItem(key);
        return null;
      }
      return item.value;
    } catch {
      return initialValue;
    }
  };

  const [value, setValue] = useState<T | null>(initialValue);

  useEffect(() => {
    setValue(read());
  }, [key]);

  const setStoredValue = (newValue: T) => {
    setValue(newValue);
    if (typeof window === "undefined") return;

    const item = { value: newValue, expiry: Date.now() + expiryMs };
    window.localStorage.setItem(key, JSON.stringify(item));
  };

  return { value, setStoredValue };
};

View source on GitHub

Related hooks