Repository: streamich/react-use (ts)

Issue:
useLocalStorage does not update value when key change
**What is the current behavior?**

When the key of the local storage change with the same hook, the initialisation is not run.

**Steps to reproduce it and if possible a minimal demo of the problem.

https://codesandbox.io/s/practical-almeida-13o7o?file=/src/App.tsx

**What is the expected behavior?**

When the key change, the initial value is set

**A little about versions:**  

see code sandbox


Pull request description:
fix(useLocalStorage): reinitialize on key change
# Description

Currently if you update the `key` prop of a `useLocalStorage` hook instance, it won't read again the local storage. So it will write the previous state to a new local storage key without initially read it. This PR forces the hook to read again local storage and update its state accordingly when the `key` prop changes. 

Fixes #1147

## Type of change

<!-- Check all relevant options. -->
- [x] Bug fix _(non-breaking change which fixes an issue)_
- [ ] 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/src/useLocalStorage.ts b/src/useLocalStorage.ts
index 2b77bfa6..def6ad80 100644
--- a/src/useLocalStorage.ts
+++ b/src/useLocalStorage.ts
@@ -1,4 +1,4 @@
-import { Dispatch, SetStateAction, useCallback, useState } from 'react';
+import { Dispatch, SetStateAction, useCallback, useState, useRef, useLayoutEffect } from 'react';
 import { isBrowser, noop } from './misc/util';
 
 type parserOptions<T> =
@@ -30,7 +30,7 @@ const useLocalStorage = <T>(
     : JSON.parse;
 
   // eslint-disable-next-line react-hooks/rules-of-hooks
-  const [state, setState] = useState<T | undefined>(() => {
+  const initializer = useRef((key: string) => {
     try {
       const serializer = options ? (options.raw ? String : options.serializer) : JSON.stringify;
 
@@ -49,6 +49,12 @@ const useLocalStorage = <T>(
     }
   });
 
+  // eslint-disable-next-line react-hooks/rules-of-hooks
+  const [state, setState] = useState<T | undefined>(() => initializer.current(key));
+
+  // eslint-disable-next-line react-hooks/rules-of-hooks
+  useLayoutEffect(() => setState(initializer.current(key)), [key]);
+
   // eslint-disable-next-line react-hooks/rules-of-hooks
   const set: Dispatch<SetStateAction<T | undefined>> = useCallback(
     (valOrFunc) => {


Test patch:
diff --git a/tests/useLocalStorage.test.ts b/tests/useLocalStorage.test.ts
index 9f642ad6..1ec54dd6 100644
--- a/tests/useLocalStorage.test.ts
+++ b/tests/useLocalStorage.test.ts
@@ -80,6 +80,19 @@ describe(useLocalStorage, () => {
     expect(foo).toEqual('baz');
   });
 
+  it('reinitializes state when key changes', () => {
+    let key = 'foo';
+    const { result, rerender } = renderHook(() => useLocalStorage(key, 'bar'));
+
+    const [, setState] = result.current;
+    act(() => setState('baz'));
+    key = 'bar';
+    rerender();
+
+    const [state] = result.current;
+    expect(state).toEqual('bar');
+  });
+
   /*
   it('keeps multiple hooks accessing the same key in sync', () => {
     localStorage.setItem('foo', 'bar');