modify useStickyState to allow for retrieving and modifying the saved state on initialization

This commit is contained in:
lingdocs 2022-04-07 18:07:23 +05:00
parent 977f37da71
commit 5864a8c492
2 changed files with 39 additions and 12 deletions

View File

@ -1,4 +1,3 @@
import { useState } from "react";
import NPPicker from "../np-picker/NPPicker"; import NPPicker from "../np-picker/NPPicker";
import VerbPicker from "../VerbPicker"; import VerbPicker from "../VerbPicker";
import TensePicker from "../TensePicker"; import TensePicker from "../TensePicker";
@ -38,8 +37,12 @@ export function PhraseBuilder(props: {
}) { }) {
const [subject, setSubject] = useStickyState<NPSelection | undefined>(undefined, "subjectNPSelection"); const [subject, setSubject] = useStickyState<NPSelection | undefined>(undefined, "subjectNPSelection");
const [mode, setMode] = useStickyState<"charts" | "phrases">("phrases", "verbExplorerMode"); const [mode, setMode] = useStickyState<"charts" | "phrases">("phrases", "verbExplorerMode");
const [verb, setVerb] = useState<VerbSelection | undefined>( const passedVerb = props.verb;
props.verb ? makeVerbSelection(props.verb, setSubject, undefined) : undefined, const [verb, setVerb] = useStickyState<VerbSelection | undefined>(
passedVerb
? (old) => makeVerbSelection(passedVerb, setSubject, old)
: undefined,
"verbExplorerVerb",
); );
const textOpts = props.opts || defaultTextOptions; const textOpts = props.opts || defaultTextOptions;
function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) { function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) {

View File

@ -1,18 +1,42 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
export default function useStickyState<T>(defaultValue: T, key: string): [ /**
value: T, * replacement from the React useState hook that will persist the state in local storage
setValue: React.Dispatch<React.SetStateAction<T>>, *
* @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<T extends string | object | boolean | undefined | null>(
defaultValue: T | ((old: T | undefined) => T),
key: string
): [
value: T,
setValue: React.Dispatch<React.SetStateAction<T>>,
] { ] {
const [value, setValue] = useState<T>(() => { const [value, setValue] = useState<T>(() => {
const stickyValue = window.localStorage.getItem(key); const v = window.localStorage.getItem(key);
if (stickyValue === null) return defaultValue; // nothing saved
try { if (v === null) {
return JSON.parse(stickyValue) as T; if (typeof defaultValue === "function") {
} catch(e) { return defaultValue(undefined);
console.error(e); }
return defaultValue; 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(() => { useEffect(() => {