diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2026-04-06 00:54:41 +0200 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2026-04-06 00:54:41 +0200 |
| commit | 1f45ef6dcd0840aa67bc42d578013b1dd086c54d (patch) | |
| tree | aaac18d7e913c3824be839c56091c280124ab0c8 /src/frontend/app/hooks/useSessionState.ts | |
| parent | b30fd3a498d09f5a6c7a7175c178ea289e3ccd78 (diff) | |
Diffstat (limited to 'src/frontend/app/hooks/useSessionState.ts')
| -rw-r--r-- | src/frontend/app/hooks/useSessionState.ts | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/frontend/app/hooks/useSessionState.ts b/src/frontend/app/hooks/useSessionState.ts new file mode 100644 index 0000000..f5a9b4e --- /dev/null +++ b/src/frontend/app/hooks/useSessionState.ts @@ -0,0 +1,39 @@ +import { useCallback, useState } from "react"; + +/** + * Like useState, but backed by sessionStorage so state survives back-navigation + * within the same browser tab. Cleared when the tab is closed. + */ +export function useSessionState<T>( + key: string, + defaultValue: T +): [T, (updater: T | ((prev: T) => T)) => void] { + const [state, setStateRaw] = useState<T>(() => { + try { + const stored = sessionStorage.getItem(key); + return stored !== null ? (JSON.parse(stored) as T) : defaultValue; + } catch { + return defaultValue; + } + }); + + const setState = useCallback( + (updater: T | ((prev: T) => T)) => { + setStateRaw((prev) => { + const next = + typeof updater === "function" + ? (updater as (prev: T) => T)(prev) + : updater; + try { + sessionStorage.setItem(key, JSON.stringify(next)); + } catch { + // sessionStorage may be unavailable (private browsing quota, etc.) + } + return next; + }); + }, + [key] + ); + + return [state, setState]; +} |
