From 84c6f0e58444a452a5e2e19d14221409d2b9d790 Mon Sep 17 00:00:00 2001 From: Aleksey Smirnov Date: Wed, 4 Jan 2023 00:09:00 +0300 Subject: [PATCH] Init value for useState hook calls once (#11802) Signed-off-by: Smirnov Aleksey Signed-off-by: Smirnov Aleksey Co-authored-by: Smirnov Aleksey --- .../react-app/src/hooks/useLocalStorage.test.tsx | 14 ++++++++++++++ web/ui/react-app/src/hooks/useLocalStorage.tsx | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/web/ui/react-app/src/hooks/useLocalStorage.test.tsx b/web/ui/react-app/src/hooks/useLocalStorage.test.tsx index 680be7850..5b5542633 100644 --- a/web/ui/react-app/src/hooks/useLocalStorage.test.tsx +++ b/web/ui/react-app/src/hooks/useLocalStorage.test.tsx @@ -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(); + }); }); diff --git a/web/ui/react-app/src/hooks/useLocalStorage.tsx b/web/ui/react-app/src/hooks/useLocalStorage.tsx index 75842e769..d321ab805 100644 --- a/web/ui/react-app/src/hooks/useLocalStorage.tsx +++ b/web/ui/react-app/src/hooks/useLocalStorage.tsx @@ -1,8 +1,9 @@ import { Dispatch, SetStateAction, useEffect, useState } from 'react'; export function useLocalStorage(localStorageKey: string, initialState: S): [S, Dispatch>] { - 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);