1
1
// ./create-storage.ts
2
2
3
3
import { Accessor , createEffect , createSignal , onCleanup , onMount } from 'solid-js' ;
4
-
5
- export type StorageType = 'localStorage' | 'sessionStorage' ;
6
-
7
- export interface StorageProperties < T > {
8
- /** Storage key */
9
- key : string ;
10
-
11
- /** Default value that will be set if value is not found in storage */
12
- defaultValue ?: T ;
13
-
14
- /** If set to true, value will be updated in createEffect after mount. Default value is true. */
15
- getInitialValueInEffect ?: boolean ;
16
-
17
- /** Function to serialize value into string to be save in storage */
18
- serialize ?: ( value : T ) => string ;
19
-
20
- /** Function to deserialize string value from storage to value */
21
- deserialize ?: ( value : string | undefined ) => T ;
22
- }
23
-
24
- function serializeJSON < T > ( value : T , hookName : string = 'use-local-storage' ) {
25
- try {
26
- return JSON . stringify ( value ) ;
27
- } catch ( error ) {
28
- throw new Error ( `bagon-hooks ${ hookName } : Failed to serialize the value` ) ;
29
- }
30
- }
31
-
32
- function deserializeJSON ( value : string | undefined ) {
33
- try {
34
- return value && JSON . parse ( value ) ;
35
- } catch {
36
- return value ;
37
- }
38
- }
39
-
40
- function createStorageHandler ( type : StorageType ) {
41
- const getItem = ( key : string ) => {
42
- try {
43
- return window [ type ] . getItem ( key ) ;
44
- } catch ( error ) {
45
- console . warn ( 'use-local-storage: Failed to get value from storage, localStorage is blocked' ) ;
46
- return null ;
47
- }
48
- } ;
49
-
50
- const setItem = ( key : string , value : string ) => {
51
- try {
52
- window [ type ] . setItem ( key , value ) ;
53
- } catch ( error ) {
54
- console . warn ( 'use-local-storage: Failed to set value to storage, localStorage is blocked' ) ;
55
- }
56
- } ;
57
-
58
- const removeItem = ( key : string ) => {
59
- try {
60
- window [ type ] . removeItem ( key ) ;
61
- } catch ( error ) {
62
- console . warn (
63
- 'use-local-storage: Failed to remove value from storage, localStorage is blocked' ,
64
- ) ;
65
- }
66
- } ;
67
-
68
- return { getItem, setItem, removeItem } ;
69
- }
4
+ import {
5
+ _createStorageHandler ,
6
+ _deserializeJSON ,
7
+ _serializeJSON ,
8
+ readLocalStorageValue ,
9
+ readValue ,
10
+ StorageProperties ,
11
+ StorageType ,
12
+ } from './utils' ;
13
+
14
+ export { readLocalStorageValue , readValue } ;
15
+ export type { StorageProperties , StorageType } ;
70
16
71
17
export function createStorage < T > ( type : StorageType , hookName : string ) {
72
18
const eventName = type === 'localStorage' ? 'bagon-local-storage' : 'bagon-session-storage' ;
73
- const { getItem, setItem, removeItem } = createStorageHandler ( type ) ;
19
+ const { getItem, setItem, removeItem } = _createStorageHandler ( type ) ;
74
20
75
21
return function useStorage ( {
76
22
key,
77
23
defaultValue,
78
24
getInitialValueInEffect = true ,
79
- deserialize = deserializeJSON ,
80
- serialize = ( value : T ) => serializeJSON ( value , hookName ) ,
25
+ deserialize = _deserializeJSON ,
26
+ serialize = ( value : T ) => _serializeJSON ( value , hookName ) ,
81
27
} : StorageProperties < T > ) {
82
28
const readStorageValue = ( skipStorage ?: boolean ) : T => {
83
29
let storageBlockedOrSkipped ;
@@ -149,10 +95,10 @@ export function createStorage<T>(type: StorageType, hookName: string) {
149
95
} ) ;
150
96
151
97
createEffect ( ( ) => {
152
- if ( defaultValue !== undefined && value === undefined ) {
98
+ if ( defaultValue !== undefined && value ( ) === undefined ) {
153
99
setStorageValue ( defaultValue ) ;
154
100
}
155
- } , [ defaultValue , value , setStorageValue ] ) ;
101
+ } ) ;
156
102
157
103
onMount ( ( ) => {
158
104
const val = readStorageValue ( ) ;
@@ -167,32 +113,6 @@ export function createStorage<T>(type: StorageType, hookName: string) {
167
113
} ;
168
114
}
169
115
170
- export function readValue ( type : StorageType ) {
171
- const { getItem } = createStorageHandler ( type ) ;
172
-
173
- return function read < T > ( {
174
- key,
175
- defaultValue,
176
- deserialize = deserializeJSON ,
177
- } : StorageProperties < T > ) {
178
- let storageBlockedOrSkipped ;
179
-
180
- try {
181
- storageBlockedOrSkipped =
182
- typeof window === 'undefined' || ! ( type in window ) || window [ type ] === null ;
183
- } catch ( _e ) {
184
- storageBlockedOrSkipped = true ;
185
- }
186
-
187
- if ( storageBlockedOrSkipped ) {
188
- return defaultValue as T ;
189
- }
190
-
191
- const storageValue = getItem ( key ) ;
192
- return storageValue !== null ? deserialize ( storageValue ) : ( defaultValue as T ) ;
193
- } ;
194
- }
195
-
196
116
// ./use-local-storage.ts
197
117
198
118
/**
@@ -201,8 +121,6 @@ export function readValue(type: StorageType) {
201
121
*
202
122
* It's also reactive across different pages.
203
123
*/
204
- export function useLocalStorage < T = string > ( props : StorageProperties < T > ) {
124
+ export function useLocalStorage < T > ( props : StorageProperties < T > ) {
205
125
return createStorage < T > ( 'localStorage' , 'use-local-storage' ) ( props ) ;
206
126
}
207
-
208
- export const readLocalStorageValue = readValue ( 'localStorage' ) ;
0 commit comments