-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseSet.ts
40 lines (32 loc) · 1.16 KB
/
useSet.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { useCallback, useMemo, useState } from 'react';
export interface StableActions<K> {
add: (key: K) => void;
remove: (key: K) => void;
toggle: (key: K) => void;
reset: () => void;
clear: () => void;
}
export interface Actions<K> extends StableActions<K> {
has: (key: K) => boolean;
}
const useSet = <K>(initialSet = new Set<K>()): [Set<K>, Actions<K>] => {
const [set, setSet] = useState(initialSet);
const stableActions = useMemo<StableActions<K>>(() => {
const add = (item: K) => setSet((prevSet) => new Set([...Array.from(prevSet), item]));
const remove = (item: K) =>
setSet((prevSet) => new Set(Array.from(prevSet).filter((i) => i !== item)));
const toggle = (item: K) =>
setSet((prevSet) =>
prevSet.has(item)
? new Set(Array.from(prevSet).filter((i) => i !== item))
: new Set([...Array.from(prevSet), item])
);
return { add, remove, toggle, reset: () => setSet(initialSet), clear: () => setSet(new Set()) };
}, [setSet]);
const utils = {
has: useCallback((item) => set.has(item), [set]),
...stableActions,
} as Actions<K>;
return [set, utils];
};
export default useSet;