@@ -2,13 +2,11 @@ import type { AbstractParserOptions } from './parser';
22import type { AbstractStorage } from './storage' ;
33
44import { isNull , isUndefined } from 'lodash' ;
5- import { useEffect , useMemo , useState } from 'react' ;
5+ import { useMemo , useSyncExternalStore } from 'react' ;
66
7- import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect' ;
87import { LocalStorageService } from './localStorage' ;
98import { STRING_PARSER } from './parser' ;
10-
11- const updates = new Map < any , Set < ( ...args : any [ ] ) => any > > ( ) ;
9+ import { useStore , stores } from './store' ;
1210
1311interface UseStorageMethod < V > {
1412 set : ( value : V ) => void ;
@@ -34,61 +32,37 @@ export function useStorage<V, K = string>(
3432
3533 const { serializer, deserializer } = isUndefined ( parser ) ? PARSER . plain : PARSER [ parser ] ;
3634
37- const res = useMemo < { readonly value : any } & UseStorageMethod < V > > ( ( ) => {
38- const updateKey = ( ov : any ) => {
39- const cbs = updates . get ( key ) ;
40- if ( cbs ) {
41- for ( const cb of cbs ) {
42- cb ( ov ) ;
43- }
44- }
45- } ;
46- return {
35+ const store = useStore ( key , SERVICE ) ;
36+ const value = useSyncExternalStore ( store . subscribe , store . getSnapshot ) ;
37+
38+ return useMemo < { readonly value : any } & UseStorageMethod < V > > (
39+ ( ) => ( {
4740 get value ( ) {
48- const originValue = SERVICE . getItem ( key ) ;
49- if ( isNull ( originValue ) ) {
41+ if ( isNull ( value ) ) {
5042 return defaultValue ?? null ;
5143 }
5244
53- return deserializer ( originValue ) ;
45+ return deserializer ( value ) ;
5446 } ,
5547 set : ( value ) => {
5648 const originValue = serializer ( value ) ;
5749 SERVICE . setItem ( key , originValue ) ;
58- updateKey ( originValue ) ;
50+ store . emitChange ( ) ;
5951 } ,
6052 remove : ( ) => {
6153 SERVICE . removeItem ( key ) ;
62- updateKey ( null ) ;
54+ store . emitChange ( ) ;
6355 } ,
64- } ;
65- } , [ SERVICE , defaultValue , deserializer , key , serializer ] ) ;
66- const [ , setOriginValue ] = useState ( SERVICE . getItem ( key ) ) ;
67-
68- // eslint-disable-next-line react-hooks/exhaustive-deps
69- useIsomorphicLayoutEffect ( ( ) => {
70- const updatesOfKey = updates . get ( key ) ;
71- if ( isUndefined ( updatesOfKey ) ) {
72- updates . set ( key , new Set ( [ setOriginValue ] ) ) ;
73- } else if ( ! updatesOfKey . has ( setOriginValue ) ) {
74- updatesOfKey . add ( setOriginValue ) ;
75- }
76- } ) ;
77-
78- useEffect ( ( ) => {
79- updates . get ( key ) ?. delete ( setOriginValue ) ;
80- } , [ key ] ) ;
81-
82- return res ;
56+ } ) ,
57+ [ SERVICE , defaultValue , deserializer , key , serializer , store , value ]
58+ ) ;
8359}
8460
8561useStorage . SERVICE = new LocalStorageService ( ) as AbstractStorage < any , any > ;
8662useStorage . PARSER = STRING_PARSER as AbstractParserOptions < any > ;
8763useStorage . clear = ( ) => {
8864 useStorage . SERVICE . clear ( ) ;
89- for ( const [ , cbs ] of updates ) {
90- for ( const cb of cbs ) {
91- cb ( null ) ;
92- }
65+ for ( const [ , store ] of stores ) {
66+ store . emitChange ( ) ;
9367 }
9468} ;
0 commit comments