Skip to content

Commit

Permalink
feat(useSet): add toggle a method (#968)
Browse files Browse the repository at this point in the history
Co-authored-by: Ward <[email protected]>
  • Loading branch information
dispix and wardoost authored Mar 3, 2020
1 parent 4153d39 commit 477614f
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
3 changes: 2 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,7 @@ const Demo = () => {
<button onClick={() => remove('hello')} disabled={!has('hello')}>
Remove 'hello'
</button>
<button onClick={() => toggle('hello')}>Toggle hello</button>
<pre>{JSON.stringify(Array.from(set), null, 2)}</pre>
</div>
);
Expand Down
21 changes: 13 additions & 8 deletions src/useSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,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 @@ -14,14 +15,18 @@ 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) =>
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) };
}, [setSet]);

const utils = {
has: useCallback(item => set.has(item), [set]),
Expand Down
3 changes: 2 additions & 1 deletion stories/useSet.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSet } from '../src';
import ShowDocs from './util/ShowDocs';

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

return (
<div>
Expand All @@ -13,6 +13,7 @@ const Demo = () => {
<button onClick={() => remove('hello')} disabled={!has('hello')}>
Remove 'hello'
</button>
<button onClick={() => toggle('hello')}>Toggle 'hello'</button>
<pre>{JSON.stringify(Array.from(set), null, 2)}</pre>
</div>
);
Expand Down
26 changes: 25 additions & 1 deletion 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 Expand Up @@ -125,13 +148,14 @@ it('should reset to initial set provided', () => {
it('should memoized its utils methods', () => {
const { result } = setUp(new Set(['a', 'b']));
const [, utils] = result.current;
const { add, remove, reset } = utils;
const { add, remove, reset, toggle } = utils;

act(() => {
add('foo');
});

expect(result.current[1].add).toBe(add);
expect(result.current[1].remove).toBe(remove);
expect(result.current[1].toggle).toBe(toggle);
expect(result.current[1].reset).toBe(reset);
});

0 comments on commit 477614f

Please sign in to comment.