Skip to content

Commit

Permalink
feat(useSet): add toggle a method
Browse files Browse the repository at this point in the history
  • Loading branch information
dispix committed Feb 13, 2020
1 parent d5fa801 commit 1abbd3b
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
5 changes: 4 additions & 1 deletion docs/useSet.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ React state hook that tracks a [Set](https://developer.mozilla.org/en-US/docs/We
import {useSet} from 'react-use';

const Demo = () => {
const [set, { add, has, remove, reset }] = useSet(new Set(['hello']));
const [set, { add, has, remove, toggle, reset }] = useSet(new Set(['hello']));

return (
<div>
Expand All @@ -17,6 +17,9 @@ const Demo = () => {
<button onClick={() => remove('hello')} disabled={!has('hello')}>
Remove 'hello'
</button>
<button onClick={() => toggle('hello')}>
{has('hello') ? 'Remove' : 'Add'} hello
</button>
<pre>{JSON.stringify(Array.from(set), null, 2)}</pre>
</div>
);
Expand Down
16 changes: 8 additions & 8 deletions src/useSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState, useMemo, useCallback } from 'react';
export interface StableActions<K> {
add: (key: K) => void;
remove: (key: K) => void;
toggle: (key: K) => void;
reset: () => void;
}

Expand All @@ -13,14 +14,13 @@ export interface Actions<K> extends StableActions<K> {
const useSet = <K>(initialSet = new Set<K>()): [Set<K>, Actions<K>] => {
const [set, setSet] = useState(initialSet);

const stableActions = useMemo<StableActions<K>>(
() => ({
add: item => setSet(prevSet => new Set([...Array.from(prevSet), item])),
remove: item => setSet(prevSet => new Set(Array.from(prevSet).filter(i => i !== item))),
reset: () => setSet(initialSet),
}),
[setSet]
);
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) => (set.has(item) ? remove : add)(item);

return { add, remove, toggle, reset: () => setSet(initialSet) };
}, [setSet]);

const utils = {
has: useCallback(item => set.has(item), [set]),
Expand Down
23 changes: 23 additions & 0 deletions tests/useSet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ it('should init set and utils', () => {
has: expect.any(Function),
add: expect.any(Function),
remove: expect.any(Function),
toggle: expect.any(Function),
reset: expect.any(Function),
});
});
Expand Down Expand Up @@ -94,6 +95,28 @@ it('should remove existing key', () => {
expect(result.current[0]).toEqual(new Set([1]));
});

it('should remove an existing key on toggle', () => {
const { result } = setUp(new Set([1, 2]));
const [, utils] = result.current;

act(() => {
utils.toggle(2);
});

expect(result.current[0]).toEqual(new Set([1]));
});

it('should add a new key on toggle', () => {
const { result } = setUp(new Set([1]));
const [, utils] = result.current;

act(() => {
utils.toggle(2);
});

expect(result.current[0]).toEqual(new Set([1, 2]));
});

it('should do nothing if removing non-existing key', () => {
const { result } = setUp(new Set(['a', 'b']));
const [, utils] = result.current;
Expand Down

0 comments on commit 1abbd3b

Please sign in to comment.