react-simplikit 0.0.29 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -114,18 +114,41 @@ var listeners = /* @__PURE__ */ new Set();
|
|
|
114
114
|
var emitListeners = () => {
|
|
115
115
|
listeners.forEach((listener) => listener());
|
|
116
116
|
};
|
|
117
|
-
function
|
|
117
|
+
function isPlainObject(value) {
|
|
118
|
+
if (typeof value !== "object") {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const proto = Object.getPrototypeOf(value);
|
|
122
|
+
const hasObjectPrototype = proto === Object.prototype;
|
|
123
|
+
if (!hasObjectPrototype) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
127
|
+
}
|
|
128
|
+
var ensureSerializable = (value) => {
|
|
129
|
+
if (value[0] != null && !["string", "number", "boolean"].includes(typeof value[0]) && !(isPlainObject(value[0]) || Array.isArray(value[0]))) {
|
|
130
|
+
throw new Error("Received a non-serializable value");
|
|
131
|
+
}
|
|
132
|
+
return value;
|
|
133
|
+
};
|
|
134
|
+
function useStorageState(key, {
|
|
135
|
+
storage = safeLocalStorage,
|
|
136
|
+
defaultValue,
|
|
137
|
+
...options
|
|
138
|
+
} = {}) {
|
|
139
|
+
const serializedDefaultValue = defaultValue;
|
|
118
140
|
const cache = (0, import_react.useRef)({
|
|
119
141
|
data: null,
|
|
120
|
-
parsed:
|
|
142
|
+
parsed: serializedDefaultValue
|
|
121
143
|
});
|
|
122
144
|
const getSnapshot = (0, import_react.useCallback)(() => {
|
|
145
|
+
const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
|
|
123
146
|
const data = storage.get(key);
|
|
124
147
|
if (data !== cache.current.data) {
|
|
125
148
|
try {
|
|
126
|
-
cache.current.parsed = data != null ?
|
|
149
|
+
cache.current.parsed = data != null ? deserializer(data) : defaultValue;
|
|
127
150
|
} catch {
|
|
128
|
-
cache.current.parsed =
|
|
151
|
+
cache.current.parsed = serializedDefaultValue;
|
|
129
152
|
}
|
|
130
153
|
cache.current.data = data;
|
|
131
154
|
}
|
|
@@ -146,21 +169,25 @@ function useStorageState(key, { storage = safeLocalStorage, defaultValue } = {})
|
|
|
146
169
|
};
|
|
147
170
|
},
|
|
148
171
|
() => getSnapshot(),
|
|
149
|
-
() =>
|
|
172
|
+
() => serializedDefaultValue
|
|
150
173
|
);
|
|
151
174
|
const setStorageState = (0, import_react.useCallback)(
|
|
152
175
|
(value) => {
|
|
176
|
+
const serializer = "serializer" in options ? options.serializer : JSON.stringify;
|
|
153
177
|
const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
|
|
154
178
|
if (nextValue == null) {
|
|
155
179
|
storage.remove(key);
|
|
156
180
|
} else {
|
|
157
|
-
storage.set(key,
|
|
181
|
+
storage.set(key, serializer(nextValue));
|
|
158
182
|
}
|
|
159
183
|
emitListeners();
|
|
160
184
|
},
|
|
161
185
|
[getSnapshot, key, storage]
|
|
162
186
|
);
|
|
163
|
-
|
|
187
|
+
const refreshStorageState = (0, import_react.useCallback)(() => {
|
|
188
|
+
setStorageState(getSnapshot());
|
|
189
|
+
}, [storage, getSnapshot, setStorageState]);
|
|
190
|
+
return ensureSerializable([storageState, setStorageState, refreshStorageState]);
|
|
164
191
|
}
|
|
165
192
|
// Annotate the CommonJS export names for ESM import in node:
|
|
166
193
|
0 && (module.exports = {
|
|
@@ -7,16 +7,20 @@ type Storage = {
|
|
|
7
7
|
clear(): void;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
type ToPrimitive<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : never;
|
|
11
10
|
type ToObject<T> = T extends unknown[] | Record<string, unknown> ? T : never;
|
|
12
|
-
type Serializable<T> = T extends string | number | boolean ?
|
|
11
|
+
type Serializable<T> = T extends string | number | boolean ? T : ToObject<T>;
|
|
13
12
|
type StorageStateOptions<T> = {
|
|
14
13
|
storage?: Storage;
|
|
15
|
-
defaultValue?:
|
|
14
|
+
defaultValue?: T;
|
|
16
15
|
};
|
|
17
16
|
type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
18
|
-
defaultValue:
|
|
17
|
+
defaultValue: T;
|
|
19
18
|
};
|
|
19
|
+
type StorageStateOptionsWithSerializer<T> = StorageStateOptions<T> & {
|
|
20
|
+
serializer: (value: Serializable<T>) => string;
|
|
21
|
+
deserializer: (value: string) => Serializable<T>;
|
|
22
|
+
};
|
|
23
|
+
type SerializableGuard<T extends readonly any[]> = T[0] extends any ? T : T[0] extends never ? 'Received a non-serializable value' : T;
|
|
20
24
|
/**
|
|
21
25
|
* @description
|
|
22
26
|
* A React hook that functions like `useState` but persists the state value in browser storage.
|
|
@@ -26,11 +30,13 @@ type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
|
26
30
|
* @param {Object} [options] - Configuration options for storage behavior.
|
|
27
31
|
* @param {Storage} [options.storage=localStorage] - The storage type (`localStorage` or `sessionStorage`). Defaults to `localStorage`.
|
|
28
32
|
* @param {T} [options.defaultValue] - The initial value if no existing value is found.
|
|
33
|
+
* @param {Function} [options.serializer] - A function to serialize the state value to a string.
|
|
34
|
+
* @param {Function} [options.deserializer] - A function to deserialize the state value from a string.
|
|
29
35
|
*
|
|
30
|
-
* @returns {readonly [state: Serializable<T> | undefined, setState: (value: SetStateAction<Serializable<T> | undefined>) => void]} A tuple:
|
|
36
|
+
* @returns {readonly [state: Serializable<T> | undefined, setState: (value: SetStateAction<Serializable<T> | undefined>) => void, refreshState: () => void]} A tuple:
|
|
31
37
|
* - state `Serializable<T> | undefined` - The current state value retrieved from storage;
|
|
32
38
|
* - setState `(value: SetStateAction<Serializable<T> | undefined>) => void` - A function to update and persist the state;
|
|
33
|
-
*
|
|
39
|
+
* - refreshState `() => void` - A function to refresh the state from storage;
|
|
34
40
|
* @example
|
|
35
41
|
* // Counter with persistent state
|
|
36
42
|
* import { useStorageState } from 'react-simplikit';
|
|
@@ -43,8 +49,9 @@ type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
|
43
49
|
* return <button onClick={() => setCount(prev => prev + 1)}>Count: {count}</button>;
|
|
44
50
|
* }
|
|
45
51
|
*/
|
|
46
|
-
declare function useStorageState<T>(key: string): readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void]
|
|
47
|
-
declare function useStorageState<T>(key: string,
|
|
48
|
-
declare function useStorageState<T>(key: string,
|
|
52
|
+
declare function useStorageState<T>(key: string): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
53
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptionsWithDefaultValue<T>): SerializableGuard<readonly [Serializable<T>, (value: SetStateAction<Serializable<T>>) => void, () => void]>;
|
|
54
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptions<T>): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
55
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptionsWithSerializer<T>): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
49
56
|
|
|
50
57
|
export { type Serializable, useStorageState };
|
package/dist/index.cjs
CHANGED
|
@@ -620,18 +620,41 @@ var listeners = /* @__PURE__ */ new Set();
|
|
|
620
620
|
var emitListeners = () => {
|
|
621
621
|
listeners.forEach((listener) => listener());
|
|
622
622
|
};
|
|
623
|
-
function
|
|
623
|
+
function isPlainObject(value) {
|
|
624
|
+
if (typeof value !== "object") {
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
const proto = Object.getPrototypeOf(value);
|
|
628
|
+
const hasObjectPrototype = proto === Object.prototype;
|
|
629
|
+
if (!hasObjectPrototype) {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
633
|
+
}
|
|
634
|
+
var ensureSerializable = (value) => {
|
|
635
|
+
if (value[0] != null && !["string", "number", "boolean"].includes(typeof value[0]) && !(isPlainObject(value[0]) || Array.isArray(value[0]))) {
|
|
636
|
+
throw new Error("Received a non-serializable value");
|
|
637
|
+
}
|
|
638
|
+
return value;
|
|
639
|
+
};
|
|
640
|
+
function useStorageState(key, {
|
|
641
|
+
storage = safeLocalStorage,
|
|
642
|
+
defaultValue,
|
|
643
|
+
...options
|
|
644
|
+
} = {}) {
|
|
645
|
+
const serializedDefaultValue = defaultValue;
|
|
624
646
|
const cache = (0, import_react19.useRef)({
|
|
625
647
|
data: null,
|
|
626
|
-
parsed:
|
|
648
|
+
parsed: serializedDefaultValue
|
|
627
649
|
});
|
|
628
650
|
const getSnapshot = (0, import_react19.useCallback)(() => {
|
|
651
|
+
const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
|
|
629
652
|
const data = storage.get(key);
|
|
630
653
|
if (data !== cache.current.data) {
|
|
631
654
|
try {
|
|
632
|
-
cache.current.parsed = data != null ?
|
|
655
|
+
cache.current.parsed = data != null ? deserializer(data) : defaultValue;
|
|
633
656
|
} catch {
|
|
634
|
-
cache.current.parsed =
|
|
657
|
+
cache.current.parsed = serializedDefaultValue;
|
|
635
658
|
}
|
|
636
659
|
cache.current.data = data;
|
|
637
660
|
}
|
|
@@ -652,21 +675,25 @@ function useStorageState(key, { storage = safeLocalStorage, defaultValue } = {})
|
|
|
652
675
|
};
|
|
653
676
|
},
|
|
654
677
|
() => getSnapshot(),
|
|
655
|
-
() =>
|
|
678
|
+
() => serializedDefaultValue
|
|
656
679
|
);
|
|
657
680
|
const setStorageState = (0, import_react19.useCallback)(
|
|
658
681
|
(value) => {
|
|
682
|
+
const serializer = "serializer" in options ? options.serializer : JSON.stringify;
|
|
659
683
|
const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
|
|
660
684
|
if (nextValue == null) {
|
|
661
685
|
storage.remove(key);
|
|
662
686
|
} else {
|
|
663
|
-
storage.set(key,
|
|
687
|
+
storage.set(key, serializer(nextValue));
|
|
664
688
|
}
|
|
665
689
|
emitListeners();
|
|
666
690
|
},
|
|
667
691
|
[getSnapshot, key, storage]
|
|
668
692
|
);
|
|
669
|
-
|
|
693
|
+
const refreshStorageState = (0, import_react19.useCallback)(() => {
|
|
694
|
+
setStorageState(getSnapshot());
|
|
695
|
+
}, [storage, getSnapshot, setStorageState]);
|
|
696
|
+
return ensureSerializable([storageState, setStorageState, refreshStorageState]);
|
|
670
697
|
}
|
|
671
698
|
|
|
672
699
|
// src/hooks/useThrottle/useThrottle.ts
|
|
@@ -7,16 +7,20 @@ type Storage = {
|
|
|
7
7
|
clear(): void;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
type ToPrimitive<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : never;
|
|
11
10
|
type ToObject<T> = T extends unknown[] | Record<string, unknown> ? T : never;
|
|
12
|
-
type Serializable<T> = T extends string | number | boolean ?
|
|
11
|
+
type Serializable<T> = T extends string | number | boolean ? T : ToObject<T>;
|
|
13
12
|
type StorageStateOptions<T> = {
|
|
14
13
|
storage?: Storage;
|
|
15
|
-
defaultValue?:
|
|
14
|
+
defaultValue?: T;
|
|
16
15
|
};
|
|
17
16
|
type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
18
|
-
defaultValue:
|
|
17
|
+
defaultValue: T;
|
|
19
18
|
};
|
|
19
|
+
type StorageStateOptionsWithSerializer<T> = StorageStateOptions<T> & {
|
|
20
|
+
serializer: (value: Serializable<T>) => string;
|
|
21
|
+
deserializer: (value: string) => Serializable<T>;
|
|
22
|
+
};
|
|
23
|
+
type SerializableGuard<T extends readonly any[]> = T[0] extends any ? T : T[0] extends never ? 'Received a non-serializable value' : T;
|
|
20
24
|
/**
|
|
21
25
|
* @description
|
|
22
26
|
* A React hook that functions like `useState` but persists the state value in browser storage.
|
|
@@ -26,11 +30,13 @@ type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
|
26
30
|
* @param {Object} [options] - Configuration options for storage behavior.
|
|
27
31
|
* @param {Storage} [options.storage=localStorage] - The storage type (`localStorage` or `sessionStorage`). Defaults to `localStorage`.
|
|
28
32
|
* @param {T} [options.defaultValue] - The initial value if no existing value is found.
|
|
33
|
+
* @param {Function} [options.serializer] - A function to serialize the state value to a string.
|
|
34
|
+
* @param {Function} [options.deserializer] - A function to deserialize the state value from a string.
|
|
29
35
|
*
|
|
30
|
-
* @returns {readonly [state: Serializable<T> | undefined, setState: (value: SetStateAction<Serializable<T> | undefined>) => void]} A tuple:
|
|
36
|
+
* @returns {readonly [state: Serializable<T> | undefined, setState: (value: SetStateAction<Serializable<T> | undefined>) => void, refreshState: () => void]} A tuple:
|
|
31
37
|
* - state `Serializable<T> | undefined` - The current state value retrieved from storage;
|
|
32
38
|
* - setState `(value: SetStateAction<Serializable<T> | undefined>) => void` - A function to update and persist the state;
|
|
33
|
-
*
|
|
39
|
+
* - refreshState `() => void` - A function to refresh the state from storage;
|
|
34
40
|
* @example
|
|
35
41
|
* // Counter with persistent state
|
|
36
42
|
* import { useStorageState } from 'react-simplikit';
|
|
@@ -43,8 +49,9 @@ type StorageStateOptionsWithDefaultValue<T> = StorageStateOptions<T> & {
|
|
|
43
49
|
* return <button onClick={() => setCount(prev => prev + 1)}>Count: {count}</button>;
|
|
44
50
|
* }
|
|
45
51
|
*/
|
|
46
|
-
declare function useStorageState<T>(key: string): readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void]
|
|
47
|
-
declare function useStorageState<T>(key: string,
|
|
48
|
-
declare function useStorageState<T>(key: string,
|
|
52
|
+
declare function useStorageState<T>(key: string): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
53
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptionsWithDefaultValue<T>): SerializableGuard<readonly [Serializable<T>, (value: SetStateAction<Serializable<T>>) => void, () => void]>;
|
|
54
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptions<T>): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
55
|
+
declare function useStorageState<T>(key: string, options: StorageStateOptionsWithSerializer<T>): SerializableGuard<readonly [Serializable<T> | undefined, (value: SetStateAction<Serializable<T> | undefined>) => void, () => void]>;
|
|
49
56
|
|
|
50
57
|
export { type Serializable, useStorageState };
|
|
@@ -88,18 +88,41 @@ var listeners = /* @__PURE__ */ new Set();
|
|
|
88
88
|
var emitListeners = () => {
|
|
89
89
|
listeners.forEach((listener) => listener());
|
|
90
90
|
};
|
|
91
|
-
function
|
|
91
|
+
function isPlainObject(value) {
|
|
92
|
+
if (typeof value !== "object") {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const proto = Object.getPrototypeOf(value);
|
|
96
|
+
const hasObjectPrototype = proto === Object.prototype;
|
|
97
|
+
if (!hasObjectPrototype) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
101
|
+
}
|
|
102
|
+
var ensureSerializable = (value) => {
|
|
103
|
+
if (value[0] != null && !["string", "number", "boolean"].includes(typeof value[0]) && !(isPlainObject(value[0]) || Array.isArray(value[0]))) {
|
|
104
|
+
throw new Error("Received a non-serializable value");
|
|
105
|
+
}
|
|
106
|
+
return value;
|
|
107
|
+
};
|
|
108
|
+
function useStorageState(key, {
|
|
109
|
+
storage = safeLocalStorage,
|
|
110
|
+
defaultValue,
|
|
111
|
+
...options
|
|
112
|
+
} = {}) {
|
|
113
|
+
const serializedDefaultValue = defaultValue;
|
|
92
114
|
const cache = useRef({
|
|
93
115
|
data: null,
|
|
94
|
-
parsed:
|
|
116
|
+
parsed: serializedDefaultValue
|
|
95
117
|
});
|
|
96
118
|
const getSnapshot = useCallback(() => {
|
|
119
|
+
const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
|
|
97
120
|
const data = storage.get(key);
|
|
98
121
|
if (data !== cache.current.data) {
|
|
99
122
|
try {
|
|
100
|
-
cache.current.parsed = data != null ?
|
|
123
|
+
cache.current.parsed = data != null ? deserializer(data) : defaultValue;
|
|
101
124
|
} catch {
|
|
102
|
-
cache.current.parsed =
|
|
125
|
+
cache.current.parsed = serializedDefaultValue;
|
|
103
126
|
}
|
|
104
127
|
cache.current.data = data;
|
|
105
128
|
}
|
|
@@ -120,21 +143,25 @@ function useStorageState(key, { storage = safeLocalStorage, defaultValue } = {})
|
|
|
120
143
|
};
|
|
121
144
|
},
|
|
122
145
|
() => getSnapshot(),
|
|
123
|
-
() =>
|
|
146
|
+
() => serializedDefaultValue
|
|
124
147
|
);
|
|
125
148
|
const setStorageState = useCallback(
|
|
126
149
|
(value) => {
|
|
150
|
+
const serializer = "serializer" in options ? options.serializer : JSON.stringify;
|
|
127
151
|
const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
|
|
128
152
|
if (nextValue == null) {
|
|
129
153
|
storage.remove(key);
|
|
130
154
|
} else {
|
|
131
|
-
storage.set(key,
|
|
155
|
+
storage.set(key, serializer(nextValue));
|
|
132
156
|
}
|
|
133
157
|
emitListeners();
|
|
134
158
|
},
|
|
135
159
|
[getSnapshot, key, storage]
|
|
136
160
|
);
|
|
137
|
-
|
|
161
|
+
const refreshStorageState = useCallback(() => {
|
|
162
|
+
setStorageState(getSnapshot());
|
|
163
|
+
}, [storage, getSnapshot, setStorageState]);
|
|
164
|
+
return ensureSerializable([storageState, setStorageState, refreshStorageState]);
|
|
138
165
|
}
|
|
139
166
|
export {
|
|
140
167
|
useStorageState
|
package/esm/index.js
CHANGED
|
@@ -571,18 +571,41 @@ var listeners = /* @__PURE__ */ new Set();
|
|
|
571
571
|
var emitListeners = () => {
|
|
572
572
|
listeners.forEach((listener) => listener());
|
|
573
573
|
};
|
|
574
|
-
function
|
|
574
|
+
function isPlainObject(value) {
|
|
575
|
+
if (typeof value !== "object") {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
const proto = Object.getPrototypeOf(value);
|
|
579
|
+
const hasObjectPrototype = proto === Object.prototype;
|
|
580
|
+
if (!hasObjectPrototype) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
584
|
+
}
|
|
585
|
+
var ensureSerializable = (value) => {
|
|
586
|
+
if (value[0] != null && !["string", "number", "boolean"].includes(typeof value[0]) && !(isPlainObject(value[0]) || Array.isArray(value[0]))) {
|
|
587
|
+
throw new Error("Received a non-serializable value");
|
|
588
|
+
}
|
|
589
|
+
return value;
|
|
590
|
+
};
|
|
591
|
+
function useStorageState(key, {
|
|
592
|
+
storage = safeLocalStorage,
|
|
593
|
+
defaultValue,
|
|
594
|
+
...options
|
|
595
|
+
} = {}) {
|
|
596
|
+
const serializedDefaultValue = defaultValue;
|
|
575
597
|
const cache = useRef10({
|
|
576
598
|
data: null,
|
|
577
|
-
parsed:
|
|
599
|
+
parsed: serializedDefaultValue
|
|
578
600
|
});
|
|
579
601
|
const getSnapshot = useCallback8(() => {
|
|
602
|
+
const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
|
|
580
603
|
const data = storage.get(key);
|
|
581
604
|
if (data !== cache.current.data) {
|
|
582
605
|
try {
|
|
583
|
-
cache.current.parsed = data != null ?
|
|
606
|
+
cache.current.parsed = data != null ? deserializer(data) : defaultValue;
|
|
584
607
|
} catch {
|
|
585
|
-
cache.current.parsed =
|
|
608
|
+
cache.current.parsed = serializedDefaultValue;
|
|
586
609
|
}
|
|
587
610
|
cache.current.data = data;
|
|
588
611
|
}
|
|
@@ -603,21 +626,25 @@ function useStorageState(key, { storage = safeLocalStorage, defaultValue } = {})
|
|
|
603
626
|
};
|
|
604
627
|
},
|
|
605
628
|
() => getSnapshot(),
|
|
606
|
-
() =>
|
|
629
|
+
() => serializedDefaultValue
|
|
607
630
|
);
|
|
608
631
|
const setStorageState = useCallback8(
|
|
609
632
|
(value) => {
|
|
633
|
+
const serializer = "serializer" in options ? options.serializer : JSON.stringify;
|
|
610
634
|
const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
|
|
611
635
|
if (nextValue == null) {
|
|
612
636
|
storage.remove(key);
|
|
613
637
|
} else {
|
|
614
|
-
storage.set(key,
|
|
638
|
+
storage.set(key, serializer(nextValue));
|
|
615
639
|
}
|
|
616
640
|
emitListeners();
|
|
617
641
|
},
|
|
618
642
|
[getSnapshot, key, storage]
|
|
619
643
|
);
|
|
620
|
-
|
|
644
|
+
const refreshStorageState = useCallback8(() => {
|
|
645
|
+
setStorageState(getSnapshot());
|
|
646
|
+
}, [storage, getSnapshot, setStorageState]);
|
|
647
|
+
return ensureSerializable([storageState, setStorageState, refreshStorageState]);
|
|
621
648
|
}
|
|
622
649
|
|
|
623
650
|
// src/hooks/useThrottle/useThrottle.ts
|