Repository: streamich/react-use
Pull request #908 (2020-01-17 15:13:01)

feat: `useMap`: allow resetting with provided value other then initial
# Description

`useMap`: Add `setAll` to allow providing entirely new object


## Type of change

<!-- Check all relevant options. -->
- [ ] Bug fix _(non-breaking change which fixes an issue)_
- [x] New feature _(non-breaking change which adds functionality)_
- [ ] **Breaking change** _(fix or feature that would cause existing functionality to not work as before)_

# Checklist
- [x] Read the [Contributing Guide](https://github.com/streamich/react-use/blob/master/CONTRIBUTING.md)
- [x] Perform a code self-review
- [x] Comment the code, particularly in hard-to-understand areas
- [x] Add documentation
- [x] Add hook's story at Storybook
- [x] Cover changes with tests
- [x] Ensure the test suite passes (`yarn test`)
- [x] Provide 100% tests coverage
- [x] Make sure code lints (`yarn lint`). Fix it with `yarn lint:fix` in case of failure.
- [x] Make sure types are fine (`yarn lint:types`).

<!-- If you can't check all the checkboxes right now - check what you can, create a Draft PR, make some changes if needed and get back to it when you will be able to put some marks in list. -->



Patch:
diff --git a/docs/useMap.md b/docs/useMap.md
index cf3273af..49821ee0 100644
--- a/docs/useMap.md
+++ b/docs/useMap.md
@@ -8,7 +8,7 @@ React state hook that tracks a value of an object.
 import {useMap} from 'react-use';
 
 const Demo = () => {
-  const [map, {set, remove, reset}] = useMap({
+  const [map, {set, setAll, remove, reset}] = useMap({
     hello: 'there',
   });
 
@@ -20,6 +20,9 @@ const Demo = () => {
       <button onClick={() => reset()}>
         Reset
       </button>
+      <button onClick={() => setAll({ hello: 'new', data: 'data' })}>
+        Set new data
+      </button>
       <button onClick={() => remove('hello')} disabled={!map.hello}>
         Remove 'hello'
       </button>
diff --git a/src/useMap.ts b/src/useMap.ts
index 236ac177..cd092844 100644
--- a/src/useMap.ts
+++ b/src/useMap.ts
@@ -2,6 +2,7 @@ import { useState, useMemo, useCallback } from 'react';
 
 export interface StableActions<T extends object> {
   set: <K extends keyof T>(key: K, value: T[K]) => void;
+  setAll: (newMap: T) => void;
   remove: <K extends keyof T>(key: K) => void;
   reset: () => void;
 }
@@ -21,6 +22,9 @@ const useMap = <T extends object = any>(initialMap: T = {} as T): [T, Actions<T>
           [key]: entry,
         }));
       },
+      setAll: (newMap: T) => {
+        set(newMap);
+      },
       remove: key => {
         set(prevMap => {
           const { [key]: omit, ...rest } = prevMap;


Test patch:
diff --git a/tests/useMap.test.ts b/tests/useMap.test.ts
index 0bcf3e21..5267cf64 100644
--- a/tests/useMap.test.ts
+++ b/tests/useMap.test.ts
@@ -11,6 +11,7 @@ it('should init map and utils', () => {
   expect(utils).toStrictEqual({
     get: expect.any(Function),
     set: expect.any(Function),
+    setAll: expect.any(Function),
     remove: expect.any(Function),
     reset: expect.any(Function),
   });
@@ -83,6 +84,17 @@ it('should override current value if setting existing key', () => {
   expect(result.current[0]).toEqual({ foo: 'qux', a: 1 });
 });
 
+it('should set new map', () => {
+  const { result } = setUp<{ foo: string; a: number; newKey?: number }>({ foo: 'bar', a: 1 });
+  const [, utils] = result.current;
+
+  act(() => {
+    utils.setAll({ foo: 'foo', a: 2 });
+  });
+
+  expect(result.current[0]).toEqual({ foo: 'foo', a: 2 });
+});
+
 it('should remove corresponding key-value pair for existing provided key', () => {
   const { result } = setUp({ foo: 'bar', a: 1 });
   const [, utils] = result.current;