From f86388338bcb7d120a903e7c0e60ed572d6c1411 Mon Sep 17 00:00:00 2001 From: zurgl Date: Mon, 20 Dec 2021 12:35:12 +0100 Subject: [PATCH] fix localstorage bug --- components/shared/Layout/index.tsx | 22 +++++--- context/index.tsx | 9 +--- hooks/useLocalStorage.ts | 2 +- types/index.ts | 5 ++ utils/context.ts | 83 ++++++++++++++++++++++-------- 5 files changed, 84 insertions(+), 37 deletions(-) diff --git a/components/shared/Layout/index.tsx b/components/shared/Layout/index.tsx index 592316e9..0a9ea837 100644 --- a/components/shared/Layout/index.tsx +++ b/components/shared/Layout/index.tsx @@ -3,9 +3,14 @@ import styled from 'styled-components'; import {Row, Col} from 'antd'; import {GlobalContext, globalStateReducer, initGlobalState} from 'context'; -import {ChainType, MarkdownForChainIdT, GlobalStateT} from 'types'; +import {ChainType, MarkdownForChainIdT, LocalStorageStateT} from 'types'; import {FOOTER_HEIGHT, GRID_LAYOUT, HEADER_HEIGHT} from 'lib/constants'; -import {isOneColumnStep, getChainId, mergeState} from 'utils/context'; +import { + isOneColumnStep, + getChainId, + prepareGlobalState, + prepareGlobalStateForStorage, +} from 'utils/context'; import {useLocalStorage} from 'hooks'; import Sidebar from './Sidebar'; @@ -20,12 +25,17 @@ type LayoutPropT = { }; const Layout = ({children, chain, markdown}: LayoutPropT) => { - const [storage, setStorage] = useLocalStorage('figment'); - const newState = mergeState(chain.id, storage, initGlobalState); - const [state, dispatch] = useReducer(globalStateReducer, newState); + const [storageState, setStorageState] = + useLocalStorage('figment'); + const newGlobalState = prepareGlobalState( + storageState, + initGlobalState, + chain.id, + ); + const [state, dispatch] = useReducer(globalStateReducer, newGlobalState); useEffect(() => { - setStorage(state); + setStorageState(prepareGlobalStateForStorage(state)); }, [state, dispatch]); const isStepOneColumn = isOneColumnStep(state); diff --git a/context/index.tsx b/context/index.tsx index 59e97c2a..4cf4ba9f 100644 --- a/context/index.tsx +++ b/context/index.tsx @@ -84,14 +84,7 @@ export const buildInitialState = (): ProtocolsStateT => { {} as ProtocolsStateT, ); }; -/* -export const initGlobalState = (currentChainId: CHAINS) => { - return { - currentChainId, - protocols: buildInitialState(), - }; -}; -*/ + export const initGlobalState = { currentChainId: undefined, protocols: buildInitialState(), diff --git a/hooks/useLocalStorage.ts b/hooks/useLocalStorage.ts index fcb2e8ac..2cc23eb7 100644 --- a/hooks/useLocalStorage.ts +++ b/hooks/useLocalStorage.ts @@ -6,7 +6,7 @@ const useLocalStorage = (key: string, initialValue?: StateT) => { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { - return initialValue; + return {}; } }); diff --git a/types/index.ts b/types/index.ts index 16715f44..f5a15751 100644 --- a/types/index.ts +++ b/types/index.ts @@ -256,6 +256,11 @@ export type LocalStorageStateT = { export type LocalStorageProtocolStateT = { currentStepId: PROTOCOL_STEPS_ID; + steps: { + [Key in PROTOCOL_STEPS_ID]: { + isCompleted: boolean; + }; + }; innerState?: InnerStateT; }; diff --git a/utils/context.ts b/utils/context.ts index 3c9b8cca..1f086a1c 100644 --- a/utils/context.ts +++ b/utils/context.ts @@ -1,5 +1,3 @@ -import {defaultsDeep, difference, keys, omit} from 'lodash'; - import { GlobalStateT, CHAINS, @@ -8,8 +6,69 @@ import { NETWORKS, ProtocolStepsT, ProtocolStepT, + LocalStorageStateT, } from 'types'; +export const prepareGlobalStateForStorage = ( + globalState: GlobalStateT, +): LocalStorageStateT => { + const chains = Object.keys(globalState.protocols) as CHAINS[]; + + return chains.reduce((acc: LocalStorageStateT, el: CHAINS) => { + const stepsId = Object.keys( + globalState.protocols[el].steps, + ) as PROTOCOL_STEPS_ID[]; + const newSteps = stepsId.reduce((acc0, stepId) => { + // @ts-ignore + acc0[stepId] = { + isCompleted: globalState.protocols[el].steps[stepId].isCompleted, + }; + return acc0; + }, {}); + acc[el] = { + currentStepId: globalState.protocols[el].currentStepId, + // @ts-ignore + steps: newSteps, + innerState: globalState.protocols[el].innerState, + }; + return acc; + }, {} as LocalStorageStateT); +}; + +export const prepareGlobalState = ( + localStorage: LocalStorageStateT, + initialGlobalState: GlobalStateT, + chainId: CHAINS, +): GlobalStateT => { + const chains = Object.keys(initialGlobalState.protocols) as CHAINS[]; + const newProtocols = chains.reduce( + (protocols: GlobalStateT['protocols'], chain: CHAINS) => { + const stepsId = Object.keys( + protocols[chain].steps, + ) as PROTOCOL_STEPS_ID[]; + const newSteps = stepsId.reduce((steps, stepId) => { + steps[stepId] = { + ...steps[stepId], + ...(localStorage ? localStorage[chain].steps[stepId] : {}), + }; + return steps; + }, protocols[chain].steps); + protocols[chain] = { + ...initialGlobalState.protocols[chain], + ...(localStorage ? localStorage[chain] : {}), + steps: newSteps, + }; + return protocols; + }, + initialGlobalState.protocols, + ); + + return { + currentChainId: chainId, + protocols: newProtocols, + }; +}; + // Global State function, upmost level export const getChainId = (state: GlobalStateT): CHAINS => { return state.currentChainId as CHAINS; @@ -230,23 +289,3 @@ export const getInnerState = (state: GlobalStateT) => { return {network, ...innerState}; }; - -export const mergeState = ( - chainId: CHAINS, - storedState: GlobalStateT, - initialState: GlobalStateT, -): GlobalStateT => { - const storageProtocols = storedState ? {...storedState.protocols} : {}; - const initProtocols = {...initialState.protocols}; - const removedKeys = difference(keys(storageProtocols), keys(initProtocols)); - - return storedState - ? ({ - currentChainId: chainId, - protocols: omit( - defaultsDeep(storageProtocols, initProtocols), - removedKeys, - ), - } as GlobalStateT) - : initialState; -};