Fix local/session storage parsing/stringifying values

The old logic stringifyed all values, including strings, which caused problems with reading external stored values (e.g., mui-mode) via the "useStorage" hook.
This commit is contained in:
schroda
2025-07-28 02:30:25 +02:00
parent fb00f51107
commit ef6c1fce56
4 changed files with 26 additions and 10 deletions

View File

@@ -30,10 +30,11 @@
<script type="module" src="./src/index.tsx"></script>
<script>
const backgroundColor = (() => {
const storageValue = window.localStorage.getItem("theme_background")
try {
return JSON.parse(window.localStorage.getItem("theme_background"))
return JSON.parse(storageValue)
} catch (e) {
return null
return storageValue
}
})();

View File

@@ -26,7 +26,7 @@ export class Storage {
return this.parseValue(this.getItem(key), defaultValue);
}
setItem(key: string, value: unknown, emitEvent: boolean = true, stringify: boolean = true): void {
setItem(key: string, value: unknown, emitEvent: boolean = true): void {
const currentValue = this.getItem(key);
const fireEvent = (valueToStore: string | undefined) => {
@@ -49,9 +49,10 @@ export class Storage {
return;
}
const stringify = typeof value !== 'string';
const valueToStore = stringify ? JSON.stringify(value) : value;
this.storage.setItem(key, valueToStore as string);
this.storage.setItem(key, valueToStore);
fireEvent(valueToStore as string);
}
}

View File

@@ -8,6 +8,7 @@
import { Dispatch, Reducer, SetStateAction, useCallback, useMemo, useReducer, useSyncExternalStore } from 'react';
import { AppStorage, Storage } from '@/lib/storage/AppStorage.ts';
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
const subscribeToStorageUpdates = (callback: () => void) => {
window.addEventListener('storage', callback);
@@ -31,16 +32,29 @@ function useStorage<T>(
const setValue = useCallback<React.Dispatch<React.SetStateAction<T | undefined>>>(
(value) => {
// Allow value to be a function so we have same API as useState
const valueToStore = value instanceof Function ? value(storage.getItemParsed(key, initialState)) : value;
const valueToStore = (() => {
if (value instanceof Function) {
const previousValue =
jsonSaveParse(storage.getItem(key) ?? '') ?? storage.getItemParsed(key, initialState);
return value(previousValue);
}
return value;
})();
storage.setItem(key, valueToStore);
},
[key],
);
const storedValue = useMemo(
() => (storedValueRaw !== null ? JSON.parse(storedValueRaw) : initialState),
[storedValueRaw, key],
);
const storedValue = useMemo(() => {
if (storedValueRaw === null) {
return initialState;
}
return jsonSaveParse(storedValueRaw) ?? storedValueRaw;
}, [storedValueRaw, key]);
return [storedValue, setValue];
}

View File

@@ -86,7 +86,7 @@ export const Appearance = () => {
setThemeMode(newMode as ThemeMode);
setMode(newMode);
// in case a non "colorSchemes" mui theme is active, "setMode" does not update the mode ("mui-mode") value
AppStorage.local.setItem('mui-mode', newMode, true, false);
AppStorage.local.setItem('mui-mode', newMode, true);
}}
>
<MenuItem key={ThemeMode.SYSTEM} value={ThemeMode.SYSTEM}>