Init value for useState hook calls once (#11802)

Signed-off-by: Smirnov Aleksey <aleksey.smirnov@sbermarket.ru>

Signed-off-by: Smirnov Aleksey <aleksey.smirnov@sbermarket.ru>
Co-authored-by: Smirnov Aleksey <aleksey.smirnov@sbermarket.ru>
This commit is contained in:
Aleksey Smirnov 2023-01-04 00:09:00 +03:00 committed by GitHub
parent 432ea873c3
commit 84c6f0e584
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 2 deletions

View file

@ -24,4 +24,18 @@ describe('useLocalStorage', () => {
expect(result.current[0]).toEqual(newValue);
expect(localStorage.getItem(key)).toEqual(JSON.stringify(newValue));
});
it('localStorage.getItem calls once', () => {
// do not prepare the initial state on every render except the first
const spyStorage = jest.spyOn(Storage.prototype, 'getItem') as jest.Mock;
const key = 'mystorage';
const initialState = { a: 1, b: 2 };
const { result } = renderHook(() => useLocalStorage(key, initialState));
const newValue = { a: 2, b: 5 };
act(() => {
result.current[1](newValue);
});
expect(spyStorage).toHaveBeenCalledTimes(1);
spyStorage.mockReset();
});
});

View file

@ -1,8 +1,9 @@
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
export function useLocalStorage<S>(localStorageKey: string, initialState: S): [S, Dispatch<SetStateAction<S>>] {
const localStorageState = JSON.parse(localStorage.getItem(localStorageKey) || JSON.stringify(initialState));
const [value, setValue] = useState(localStorageState);
const [value, setValue] = useState(() =>
JSON.parse(localStorage.getItem(localStorageKey) || JSON.stringify(initialState))
);
useEffect(() => {
const serializedState = JSON.stringify(value);