feat(useSet): add toggle a method (#968)

Co-authored-by: Ward <wardoosterlijnck@gmail.com>
This commit is contained in:
Octave Raimbault 2020-03-03 04:00:40 +01:00 committed by GitHub
parent 4153d39251
commit 477614f9ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 11 deletions

View File

@ -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>
@ -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>
);

View File

@ -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;
}
@ -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]),

View File

@ -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>
@ -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>
);

View File

@ -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),
});
});
@ -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;
@ -125,7 +148,7 @@ 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');
@ -133,5 +156,6 @@ it('should memoized its utils methods', () => {
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);
});