1- import { useState , useEffect , useRef , useCallback , useMemo } from "react" ;
1+ import { useState , useEffect , useRef , useCallback } from "react" ;
22import type {
33 State ,
44 StoreAPI ,
@@ -20,11 +20,8 @@ const createStore = <T extends State>(
2020 const keyListeners = new Map < string , Set < Listener > > ( ) ;
2121 const globalListeners = new Set < GlobalListener < T > > ( ) ;
2222
23- // check store is isDestroyed or not
24- let isDestroyed = false ;
25-
2623 const notify = ( changedKeys : string [ ] ) => {
27- if ( isDestroyed || changedKeys . length === 0 ) return ;
24+ if ( changedKeys . length === 0 ) return ;
2825
2926 changedKeys . forEach ( ( key ) => {
3027 const listeners = keyListeners . get ( key ) ;
@@ -39,36 +36,25 @@ const createStore = <T extends State>(
3936 function getState ( ) : T ;
4037 function getState < K extends keyof T > ( key : K ) : T [ K ] ;
4138 function getState < K extends keyof T > ( key ?: K ) {
42- if ( isDestroyed ) {
43- console . warn ( "Store has been destroyed" ) ;
44- return key === undefined ? ( { } as T ) : ( undefined as T [ K ] ) ;
45- }
4639 return key === undefined ? state : state [ key ] ;
4740 }
4841
4942 const setState = ( partial : PartialState < T > ) => {
50- if ( isDestroyed ) {
51- console . warn ( "Cannot setState on destroyed store" ) ;
52- return ;
53- }
54-
5543 const nextState = typeof partial === "function" ? partial ( state ) : partial ;
5644 if ( ! nextState || typeof nextState !== "object" ) return ;
5745
5846 const changedKeys : string [ ] = [ ] ;
59- const updates : Record < string , any > = { } ;
6047 let hasChanges = false ;
6148
6249 Object . keys ( nextState ) . forEach ( ( key ) => {
6350 if ( ! isEqual ( state [ key ] , nextState [ key ] ) ) {
64- updates [ key ] = nextState [ key ] ;
6551 changedKeys . push ( key ) ;
6652 hasChanges = true ;
6753 }
6854 } ) ;
6955
7056 if ( hasChanges ) {
71- state = { ...state , ...updates } as T ;
57+ state = { ...state , ...nextState } as T ;
7258 notify ( changedKeys ) ;
7359 }
7460 } ;
@@ -77,11 +63,6 @@ const createStore = <T extends State>(
7763 keyOrListener : string | GlobalListener < T > ,
7864 listener ?: Listener
7965 ) => {
80- if ( isDestroyed ) {
81- console . warn ( "Cannot subscribe to destroyed store" ) ;
82- return ( ) => { } ;
83- }
84-
8566 if ( typeof keyOrListener === "function" ) {
8667 globalListeners . add ( keyOrListener ) ;
8768 return ( ) => globalListeners . delete ( keyOrListener ) ;
@@ -104,42 +85,12 @@ const createStore = <T extends State>(
10485 } ;
10586 } ) as StoreAPI < T > [ "subscribe" ] ;
10687
107- const cleanup = ( ) => {
108- keyListeners . clear ( ) ;
109- globalListeners . clear ( ) ;
110-
111- state = { } as T ;
112- isDestroyed = true ;
113-
114- console . log ( "Store has been cleaned up and destroyed" ) ;
115- } ;
116-
117- const checkIsDestroyed = ( ) => isDestroyed ;
118-
11988 const useStore = ( ) : [ T , ( partial : PartialState < T > ) => void ] => {
120- const [ localState , setLocalState ] = useState < T > ( ( ) => getState ( ) ) ;
121- const mountedRef = useRef ( true ) ;
122-
123- useEffect ( ( ) => {
124- if ( isDestroyed ) return ;
125-
126- setLocalState ( getState ( ) ) ;
127- const unsubscribe = subscribe ( ( newState : T ) => {
128- if ( mountedRef . current && ! isDestroyed ) {
129- setLocalState ( newState ) ;
130- }
131- } ) ;
132-
133- return ( ) => {
134- mountedRef . current = false ;
135- unsubscribe ( ) ;
136- } ;
137- } , [ ] ) ;
89+ const [ localState , setLocalState ] = useState < T > ( state ) ;
13890
13991 useEffect ( ( ) => {
140- return ( ) => {
141- mountedRef . current = false ;
142- } ;
92+ setLocalState ( state ) ;
93+ return subscribe ( setLocalState ) ;
14394 } , [ ] ) ;
14495
14596 return [ localState , setState ] ;
@@ -148,28 +99,25 @@ const createStore = <T extends State>(
14899 const useStoreKey = < K extends keyof T > (
149100 key : K
150101 ) : [ T [ K ] , ( value : SetStateAction < T [ K ] > ) => void ] => {
151- const [ value , setValue ] = useState < T [ K ] > ( ( ) => getState ( key ) ) ;
102+ const [ value , setValue ] = useState < T [ K ] > ( state [ key ] ) ;
152103 const mountedRef = useRef ( true ) ;
153104
154105 useEffect ( ( ) => {
155- if ( isDestroyed ) return ;
156-
157- setValue ( getState ( key ) ) ;
106+ setValue ( state [ key ] ) ;
158107 const unsubscribe = subscribe ( key as string , ( newValue : T [ K ] ) => {
159- if ( mountedRef . current && ! isDestroyed ) {
108+ if ( mountedRef . current ) {
160109 setValue ( newValue ) ;
161110 }
162111 } ) ;
163112
164113 return ( ) => {
114+ mountedRef . current = false ;
165115 unsubscribe ( ) ;
166116 } ;
167117 } , [ key ] ) ;
168118
169119 const setKeyValue = useCallback (
170120 ( newValue : SetStateAction < T [ K ] > ) => {
171- if ( isDestroyed ) return ;
172-
173121 setState (
174122 ( prevState ) =>
175123 ( {
@@ -183,12 +131,6 @@ const createStore = <T extends State>(
183131 [ key ]
184132 ) ;
185133
186- useEffect ( ( ) => {
187- return ( ) => {
188- mountedRef . current = false ;
189- } ;
190- } , [ ] ) ;
191-
192134 return [ value , setKeyValue ] ;
193135 } ;
194136
@@ -202,68 +144,57 @@ const createStore = <T extends State>(
202144 | ( ( values : Pick < T , K > ) => Partial < Pick < T , K > > )
203145 ) => void
204146 ] => {
205- const stableKeys = useMemo ( ( ) => [ ... keys ] , [ keys . join ( "," ) ] ) ;
206- const [ values , setValues ] = useState < Pick < T , K > > ( ( ) => {
147+ const keysDep = keys . join ( "," ) ;
148+ const getValues = ( ) => {
207149 const result = { } as Pick < T , K > ;
208- stableKeys . forEach ( ( key ) => {
209- result [ key ] = getState ( key ) ;
150+ keys . forEach ( ( key ) => {
151+ result [ key ] = state [ key ] ;
210152 } ) ;
211153 return result ;
212- } ) ;
154+ } ;
213155
156+ const [ values , setValues ] = useState < Pick < T , K > > ( getValues ) ;
214157 const mountedRef = useRef ( true ) ;
215158
216159 useEffect ( ( ) => {
217- if ( isDestroyed ) return ;
218-
219- const initialValues = { } as Pick < T , K > ;
220- stableKeys . forEach ( ( key ) => {
221- initialValues [ key ] = getState ( key ) ;
222- } ) ;
223- setValues ( initialValues ) ;
224-
225- const unsubscribes = stableKeys . map ( ( key ) =>
226- subscribe ( key as string , ( newValue : T [ K ] ) => {
227- if ( mountedRef . current && ! isDestroyed ) {
228- setValues ( ( prev ) => ( { ...prev , [ key ] : newValue } ) ) ;
160+ setValues ( getValues ( ) ) ;
161+ const unsubscribes = keys . map ( ( key ) =>
162+ subscribe ( key as string , ( ) => {
163+ if ( mountedRef . current ) {
164+ setValues ( ( prev ) => ( { ...prev , [ key ] : state [ key ] } ) ) ;
229165 }
230166 } )
231167 ) ;
232168
233- return ( ) => unsubscribes . forEach ( ( unsub ) => unsub ( ) ) ;
234- } , [ stableKeys . join ( "," ) ] ) ;
169+ return ( ) => {
170+ mountedRef . current = false ;
171+ unsubscribes . forEach ( ( unsub ) => unsub ( ) ) ;
172+ } ;
173+ } , [ keysDep ] ) ;
235174
236175 const setKeyValues = useCallback (
237176 (
238177 updates :
239178 | Partial < Pick < T , K > >
240179 | ( ( values : Pick < T , K > ) => Partial < Pick < T , K > > )
241180 ) => {
242- if ( isDestroyed ) return ;
243-
244181 const result =
245182 typeof updates === "function" ? updates ( values ) : updates ;
246- const filteredUpdates : Record < string , any > = { } ;
247183
248- Object . keys ( result ) . forEach ( ( key ) => {
249- if ( stableKeys . includes ( key as K ) ) {
250- filteredUpdates [ key ] = result [ key as keyof typeof result ] ;
184+ const filteredUpdates = Object . keys ( result ) . reduce ( ( acc , key ) => {
185+ if ( keys . includes ( key as K ) ) {
186+ acc [ key ] = result [ key as keyof typeof result ] ;
251187 }
252- } ) ;
188+ return acc ;
189+ } , { } as Record < string , any > ) ;
253190
254191 if ( Object . keys ( filteredUpdates ) . length > 0 ) {
255192 setState ( filteredUpdates as Partial < T > ) ;
256193 }
257194 } ,
258- [ stableKeys . join ( "," ) , values ]
195+ [ keysDep , values ]
259196 ) ;
260197
261- useEffect ( ( ) => {
262- return ( ) => {
263- mountedRef . current = false ;
264- } ;
265- } , [ ] ) ;
266-
267198 return [ values , setKeyValues ] ;
268199 } ;
269200
@@ -274,15 +205,7 @@ const createStore = <T extends State>(
274205 useStore,
275206 useStoreKey,
276207 useStoreKeys,
277- cleanup,
278- isDestroyed : checkIsDestroyed ,
279208 } ;
280209} ;
281210
282211export default createStore ;
283-
284- // const store = createStore({ count: 0 });
285- //// store.cleanup();
286- //// if (store.isDestroyed()) {
287- // console.log('Store is destroyed');
288- // }
0 commit comments