-
Notifications
You must be signed in to change notification settings - Fork 0
/
create-store.ts
49 lines (42 loc) · 1.41 KB
/
create-store.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { useState } from 'react'
import { InitStoreOptions, SetState, StoreApi, StoreInitializer, initStore } from 'dev-disk'
import { useSyncStoreSlice } from './use-sync-store-slice.ts'
// ----------------------------------------
// Type definitions
export type UseStore<
T extends Record<string, any>,
TProps extends Record<string, any> = Record<string, never>,
> = {
<U = T>(selector?: (state: T) => U): U
} & StoreApi<T> &
TProps
// ----------------------------------------
// Source code
export const createStore = <
T extends Record<string, any>,
TProps extends Record<string, any> = Record<string, never>,
>(
initializer: StoreInitializer<T, TProps>,
options: InitStoreOptions<T> = {},
): UseStore<T, TProps> => {
const storeApi = initStore(initializer, options)
const useStore = <U = T>(selector?: (state: T) => U) => {
return useSyncStoreSlice(storeApi, selector)
}
return Object.assign(useStore, storeApi)
}
export const useInitialValue = <T extends Record<string, any>>(
storeApi: StoreApi<T>,
value: SetState<T>,
) => {
useState(() => {
// Note: Put `storeApi.set(value)` inside of useState to ensure it is only invoked once.
if (storeApi.getSubscribers().size > 0) {
console.warn(
'The store already have subscriber.',
'Consider calling setInitialValue on higher component, before any component subscribed.',
)
}
storeApi.set(value)
})
}