From 477614f9ef84d3cfa75f9c8a97dbc73d30dd411d Mon Sep 17 00:00:00 2001 From: Octave Raimbault Date: Tue, 3 Mar 2020 04:00:40 +0100 Subject: [PATCH] feat(useSet): add toggle a method (#968) Co-authored-by: Ward --- docs/useSet.md | 3 ++- src/useSet.ts | 21 +++++++++++++-------- stories/useSet.story.tsx | 3 ++- tests/useSet.test.ts | 26 +++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/docs/useSet.md b/docs/useSet.md index 8b6f620ac8..554072023b 100644 --- a/docs/useSet.md +++ b/docs/useSet.md @@ -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 (
@@ -17,6 +17,7 @@ const Demo = () => { +
{JSON.stringify(Array.from(set), null, 2)}
); diff --git a/src/useSet.ts b/src/useSet.ts index 9498413d67..4ceca00587 100644 --- a/src/useSet.ts +++ b/src/useSet.ts @@ -4,6 +4,7 @@ import { useState, useMemo, useCallback } from 'react'; export interface StableActions { add: (key: K) => void; remove: (key: K) => void; + toggle: (key: K) => void; reset: () => void; } @@ -14,14 +15,18 @@ export interface Actions extends StableActions { const useSet = (initialSet = new Set()): [Set, Actions] => { const [set, setSet] = useState(initialSet); - const stableActions = useMemo>( - () => ({ - 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>(() => { + 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]), diff --git a/stories/useSet.story.tsx b/stories/useSet.story.tsx index 9166b2a3db..f1b5e05059 100644 --- a/stories/useSet.story.tsx +++ b/stories/useSet.story.tsx @@ -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 (
@@ -13,6 +13,7 @@ const Demo = () => { +
{JSON.stringify(Array.from(set), null, 2)}
); diff --git a/tests/useSet.test.ts b/tests/useSet.test.ts index 20e734b430..787eb5e4b9 100644 --- a/tests/useSet.test.ts +++ b/tests/useSet.test.ts @@ -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); });