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:
@@ -30,10 +30,11 @@
|
|||||||
<script type="module" src="./src/index.tsx"></script>
|
<script type="module" src="./src/index.tsx"></script>
|
||||||
<script>
|
<script>
|
||||||
const backgroundColor = (() => {
|
const backgroundColor = (() => {
|
||||||
|
const storageValue = window.localStorage.getItem("theme_background")
|
||||||
try {
|
try {
|
||||||
return JSON.parse(window.localStorage.getItem("theme_background"))
|
return JSON.parse(storageValue)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null
|
return storageValue
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export class Storage {
|
|||||||
return this.parseValue(this.getItem(key), defaultValue);
|
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 currentValue = this.getItem(key);
|
||||||
|
|
||||||
const fireEvent = (valueToStore: string | undefined) => {
|
const fireEvent = (valueToStore: string | undefined) => {
|
||||||
@@ -49,9 +49,10 @@ export class Storage {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stringify = typeof value !== 'string';
|
||||||
const valueToStore = stringify ? JSON.stringify(value) : value;
|
const valueToStore = stringify ? JSON.stringify(value) : value;
|
||||||
|
|
||||||
this.storage.setItem(key, valueToStore as string);
|
this.storage.setItem(key, valueToStore);
|
||||||
fireEvent(valueToStore as string);
|
fireEvent(valueToStore as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import { Dispatch, Reducer, SetStateAction, useCallback, useMemo, useReducer, useSyncExternalStore } from 'react';
|
import { Dispatch, Reducer, SetStateAction, useCallback, useMemo, useReducer, useSyncExternalStore } from 'react';
|
||||||
import { AppStorage, Storage } from '@/lib/storage/AppStorage.ts';
|
import { AppStorage, Storage } from '@/lib/storage/AppStorage.ts';
|
||||||
|
import { jsonSaveParse } from '@/lib/HelperFunctions.ts';
|
||||||
|
|
||||||
const subscribeToStorageUpdates = (callback: () => void) => {
|
const subscribeToStorageUpdates = (callback: () => void) => {
|
||||||
window.addEventListener('storage', callback);
|
window.addEventListener('storage', callback);
|
||||||
@@ -31,16 +32,29 @@ function useStorage<T>(
|
|||||||
const setValue = useCallback<React.Dispatch<React.SetStateAction<T | undefined>>>(
|
const setValue = useCallback<React.Dispatch<React.SetStateAction<T | undefined>>>(
|
||||||
(value) => {
|
(value) => {
|
||||||
// Allow value to be a function so we have same API as useState
|
// 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);
|
storage.setItem(key, valueToStore);
|
||||||
},
|
},
|
||||||
[key],
|
[key],
|
||||||
);
|
);
|
||||||
|
|
||||||
const storedValue = useMemo(
|
const storedValue = useMemo(() => {
|
||||||
() => (storedValueRaw !== null ? JSON.parse(storedValueRaw) : initialState),
|
if (storedValueRaw === null) {
|
||||||
[storedValueRaw, key],
|
return initialState;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return jsonSaveParse(storedValueRaw) ?? storedValueRaw;
|
||||||
|
}, [storedValueRaw, key]);
|
||||||
|
|
||||||
return [storedValue, setValue];
|
return [storedValue, setValue];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export const Appearance = () => {
|
|||||||
setThemeMode(newMode as ThemeMode);
|
setThemeMode(newMode as ThemeMode);
|
||||||
setMode(newMode);
|
setMode(newMode);
|
||||||
// in case a non "colorSchemes" mui theme is active, "setMode" does not update the mode ("mui-mode") value
|
// 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}>
|
<MenuItem key={ThemeMode.SYSTEM} value={ThemeMode.SYSTEM}>
|
||||||
|
|||||||
Reference in New Issue
Block a user