From 5864a8c492f475c254971bd2afa28e8a8952b49b Mon Sep 17 00:00:00 2001 From: lingdocs <71590811+lingdocs@users.noreply.github.com> Date: Thu, 7 Apr 2022 18:07:23 +0500 Subject: [PATCH] modify useStickyState to allow for retrieving and modifying the saved state on initialization --- .../phrase-builder/PhraseBuilder.tsx | 9 ++-- src/useStickyState.ts | 42 +++++++++++++++---- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/components/phrase-builder/PhraseBuilder.tsx b/src/components/phrase-builder/PhraseBuilder.tsx index 35bff8e..c4a4388 100644 --- a/src/components/phrase-builder/PhraseBuilder.tsx +++ b/src/components/phrase-builder/PhraseBuilder.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import NPPicker from "../np-picker/NPPicker"; import VerbPicker from "../VerbPicker"; import TensePicker from "../TensePicker"; @@ -38,8 +37,12 @@ export function PhraseBuilder(props: { }) { const [subject, setSubject] = useStickyState(undefined, "subjectNPSelection"); const [mode, setMode] = useStickyState<"charts" | "phrases">("phrases", "verbExplorerMode"); - const [verb, setVerb] = useState( - props.verb ? makeVerbSelection(props.verb, setSubject, undefined) : undefined, + const passedVerb = props.verb; + const [verb, setVerb] = useStickyState( + passedVerb + ? (old) => makeVerbSelection(passedVerb, setSubject, old) + : undefined, + "verbExplorerVerb", ); const textOpts = props.opts || defaultTextOptions; function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) { diff --git a/src/useStickyState.ts b/src/useStickyState.ts index a617ef8..ce824e3 100644 --- a/src/useStickyState.ts +++ b/src/useStickyState.ts @@ -1,18 +1,42 @@ import { useEffect, useState } from "react"; -export default function useStickyState(defaultValue: T, key: string): [ - value: T, - setValue: React.Dispatch>, +/** + * replacement from the React useState hook that will persist the state in local storage + * + * @param defaultValue The default value to use if there was nothing saved previously OR + * a function that will take the saved value and return a modified new value to start with + * @param key a key for saving the state in locolStorage + * @returns + */ +export default function useStickyState( + defaultValue: T | ((old: T | undefined) => T), + key: string +): [ + value: T, + setValue: React.Dispatch>, ] { const [value, setValue] = useState(() => { - const stickyValue = window.localStorage.getItem(key); - if (stickyValue === null) return defaultValue; - try { - return JSON.parse(stickyValue) as T; - } catch(e) { - console.error(e); + const v = window.localStorage.getItem(key); + // nothing saved + if (v === null) { + if (typeof defaultValue === "function") { + return defaultValue(undefined); + } return defaultValue; } + // something saved before + try { + const old = JSON.parse(v) as T; + if (typeof defaultValue === "function") { + return defaultValue(old); + } + return defaultValue; + } catch (e) { + console.error("error parsting saved state from stickState"); + return (typeof defaultValue === "function") + ? defaultValue(undefined) + : defaultValue; + } }); useEffect(() => {