State

useMap

Manage a Map as immutable React state.

Demo

  • theme : dark
  • lang : en

Usage

use-map.tsxtsx
import { useMap } from "hookli";

export function Demo() {
  const [map, { set, remove, reset }] = useMap<string, string>([
    ["theme", "dark"],
  ]);

  return (
    <div>
      <button onClick={() => set("lang", "en")}>Set lang</button>
      <button onClick={() => remove("theme")}>Remove theme</button>
      <button onClick={reset}>Reset</button>
      <ul>
        {[...map.entries()].map(([key, value]) => (
          <li key={key}>{key}: {value}</li>
        ))}
      </ul>
    </div>
  );
}

API

useMap.d.tsts
useMap<K, V>(initialState?: MapOrEntries<K, V>): [ReadOnlyMap<K, V>, UseMapActions<K, V>]

Parameters

NameTypeDefaultDescription
initialStateMapOrEntries<K, V>new Map()Initial entries as a Map or an array of [key, value] pairs.

Returns

NameTypeDescription
[0] mapReadOnlyMap<K, V>A read-only view of the map — the mutating set/clear/delete methods are omitted; use the actions instead. get, has, size and iteration remain.
[1] actionsUseMapActions<K, V>Stable helpers that replace the map with a fresh copy so React re-renders — see below.

UseMapActions

The second tuple element — the map mutation helpers.

NameTypeDescription
set(key: K, value: V) => voidAdds or updates one entry.
setAll(entries: MapOrEntries<K, V>) => voidReplaces every entry with the given Map or [key, value] pairs.
remove(key: K) => voidDeletes the entry for the given key.
reset() => voidEmpties the map.

Hook

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

src/hooks/use-map/use-map.tstsx
import { useCallback, useState } from "react";

export type MapOrEntries<K, V> = Map<K, V> | [K, V][];

export interface UseMapActions<K, V> {
  set: (key: K, value: V) => void;
  setAll: (entries: MapOrEntries<K, V>) => void;
  remove: (key: K) => void;
  reset: () => void;
}

export type ReadOnlyMap<K, V> = Omit<Map<K, V>, "set" | "clear" | "delete">;

export type UseMapReturn<K, V> = [ReadOnlyMap<K, V>, UseMapActions<K, V>];

export function useMap<K, V>(
  initialState: MapOrEntries<K, V> = new Map(),
): UseMapReturn<K, V> {
  const [map, setMap] = useState(() => new Map(initialState));

  const set = useCallback((key: K, value: V) => {
    setMap((prev) => {
      const next = new Map(prev);
      next.set(key, value);
      return next;
    });
  }, []);

  const setAll = useCallback((entries: MapOrEntries<K, V>) => {
    setMap(new Map(entries));
  }, []);

  const remove = useCallback((key: K) => {
    setMap((prev) => {
      const next = new Map(prev);
      next.delete(key);
      return next;
    });
  }, []);

  const reset = useCallback(() => {
    setMap(new Map());
  }, []);

  return [map, { set, setAll, remove, reset }];
}

View source on GitHub

Related hooks