From ef1241e292b71cf13c588af3633aaa3d817ca0f5 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Tue, 16 Apr 2024 13:04:00 +0200 Subject: [PATCH] Persist user interactions (#7) * persist all user interactions * move localstorage logic to custom hook * hook rewrite --- features/strategies/components/Buy.tsx | 5 ++- features/strategies/components/Swap/Swap.tsx | 17 ++++++--- features/strategies/hooks/index.tsx | 1 + .../strategies/hooks/use-persistent-state.ts | 36 +++++++++++++++++++ 4 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 features/strategies/hooks/use-persistent-state.ts diff --git a/features/strategies/components/Buy.tsx b/features/strategies/components/Buy.tsx index bf8553e..3db14d8 100644 --- a/features/strategies/components/Buy.tsx +++ b/features/strategies/components/Buy.tsx @@ -1,16 +1,15 @@ 'use client' -import { useState } from 'react' import { useDebounce } from 'use-debounce' import { ratioOceanToAsi, ratioAgixToAsi, ratioFetToAsi } from '@/constants' import { usePrices } from '@/features/prices' import { getTokenBySymbol } from '@/lib' -import { FormAmount, Result } from '@/features/strategies' +import { FormAmount, Result, usePersistentState } from '@/features/strategies' import stylesShared from '@/features/strategies/styles/shared.module.css' export function Buy() { const { prices, isValidating, isLoading } = usePrices() - const [amount, setAmount] = useState(100) + const [amount, setAmount] = usePersistentState('buyAmount', 100) const [debouncedAmount] = useDebounce(amount, 500) return ( diff --git a/features/strategies/components/Swap/Swap.tsx b/features/strategies/components/Swap/Swap.tsx index 5ae6f46..9bd02f0 100644 --- a/features/strategies/components/Swap/Swap.tsx +++ b/features/strategies/components/Swap/Swap.tsx @@ -1,17 +1,24 @@ 'use client' -import { useState } from 'react' import { useDebounce } from 'use-debounce' import { SwapResults } from './Results' import { TokenSymbol } from '@/types' -import { type Market, FormAmount, FormMarket } from '@/features/strategies' +import { + type Market, + FormAmount, + FormMarket, + usePersistentState +} from '@/features/strategies' import stylesShared from '@/features/strategies/styles/shared.module.css' export function Swap() { - const [amount, setAmount] = useState(100) + const [amount, setAmount] = usePersistentState('swapAmount', 100) const [debouncedAmount] = useDebounce(amount, 500) - const [tokenSymbol, setTokenSymbol] = useState('OCEAN') - const [market, setMarket] = useState('all') + const [tokenSymbol, setTokenSymbol] = usePersistentState( + 'swapTokenSymbol', + 'OCEAN' + ) + const [market, setMarket] = usePersistentState('swapMarket', 'all') return (
diff --git a/features/strategies/hooks/index.tsx b/features/strategies/hooks/index.tsx index 1905d1d..0644315 100644 --- a/features/strategies/hooks/index.tsx +++ b/features/strategies/hooks/index.tsx @@ -1 +1,2 @@ export * from './use-quote' +export * from './use-persistent-state' diff --git a/features/strategies/hooks/use-persistent-state.ts b/features/strategies/hooks/use-persistent-state.ts new file mode 100644 index 0000000..f881bb8 --- /dev/null +++ b/features/strategies/hooks/use-persistent-state.ts @@ -0,0 +1,36 @@ +'use client' + +import { useState, useEffect, Dispatch, SetStateAction } from 'react' + +function parse(value: string) { + try { + return JSON.parse(value) + } catch { + return value + } +} + +export function usePersistentState( + key: string, + initialState?: T | (() => T) +): [T, Dispatch>] { + const [state, setState] = useState(initialState as T) + + function changeValue(state: SetStateAction) { + setState(state) + localStorage.setItem(key, JSON.stringify(state)) + } + + useEffect(() => { + const stored = localStorage.getItem(key) + + if (!stored) { + setState(initialState as T) + localStorage.setItem(key, JSON.stringify(initialState)) + } else { + setState(parse(stored)) + } + }, [initialState, key]) + + return [state, changeValue] +}