useMap()

This React hook provides an API to interact with a Map (Documentation)

It takes as initial entries a Map or an array like [["key": "value"], [..]] or nothing and returns:

  • An array with an instance of Map (including: foreach, get, has, entries, keys, values, size)
  • And an object of methods (set, setAll, remove, reset)

Make sure to use these methods to update the map, a map.set(..) would not re-render the component.


Why use Map instead of an object ?

Map is an iterable, a simple hash and it performs better in storing large data (Read more).

The Hook

1import { useCallback, useState } from 'react'
2
3export type MapOrEntries<K, V> = Map<K, V> | [K, V][]
4
5// Public interface
6export interface Actions<K, V> {
7 set: (key: K, value: V) => void
8 setAll: (entries: MapOrEntries<K, V>) => void
9 remove: (key: K) => void
10 reset: Map<K, V>['clear']
11}
12
13// We hide some setters from the returned map to disable autocompletion
14type Return<K, V> = [Omit<Map<K, V>, 'set' | 'clear' | 'delete'>, Actions<K, V>]
15
16function useMap<K, V>(
17 initialState: MapOrEntries<K, V> = new Map(),
18): Return<K, V> {
19 const [map, setMap] = useState(new Map(initialState))
20
21 const actions: Actions<K, V> = {
22 set: useCallback((key, value) => {
23 setMap(prev => {
24 const copy = new Map(prev)
25 copy.set(key, value)
26 return copy
27 })
28 }, []),
29
30 setAll: useCallback(entries => {
31 setMap(() => new Map(entries))
32 }, []),
33
34 remove: useCallback(key => {
35 setMap(prev => {
36 const copy = new Map(prev)
37 copy.delete(key)
38 return copy
39 })
40 }, []),
41
42 reset: useCallback(() => {
43 setMap(() => new Map())
44 }, []),
45 }
46
47 return [map, actions]
48}
49
50export default useMap

Usage

1import { Fragment } from 'react'
2
3import { MapOrEntries, useMap } from 'usehooks-ts'
4
5const initialValues: MapOrEntries<string, string> = [['key', '🆕']]
6const otherValues: MapOrEntries<string, string> = [
7 ['hello', '👋'],
8 ['data', '📦'],
9]
10
11export default function Component() {
12 const [map, actions] = useMap<string, string>(initialValues)
13
14 const set = () => actions.set(String(Date.now()), '📦')
15 const setAll = () => actions.setAll(otherValues)
16 const reset = () => actions.reset()
17 const remove = () => actions.remove('hello')
18
19 return (
20 <div>
21 <button onClick={set}>Add</button>
22 <button onClick={reset}>Reset</button>
23 <button onClick={setAll}>Set new data</button>
24 <button onClick={remove} disabled={!map.get('hello')}>
25 {'Remove "hello"'}
26 </button>
27
28 <pre>
29 Map (
30 {Array.from(map.entries()).map(([key, value]) => (
31 <Fragment key={key}>{`\n ${key}: ${value}`}</Fragment>
32 ))}
33 <br />)
34 </pre>
35 </div>
36 )
37}

Edit on CodeSandbox

See a way to make this page better?
Edit there »