forked from pmndrs/zustand
-
Notifications
You must be signed in to change notification settings - Fork 0
/
react.ts
100 lines (86 loc) · 3.04 KB
/
react.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { useDebugValue } from 'react'
// import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector'
// This doesn't work in ESM, because use-sync-external-store only exposes CJS.
// See: https://github.com/pmndrs/valtio/issues/452
// The following is a workaround until ESM is supported.
import useSyncExternalStoreExports from 'use-sync-external-store/shim/with-selector'
import { createStore } from './vanilla'
import type {
Mutate,
StateCreator,
StoreApi,
StoreMutatorIdentifier,
} from './vanilla'
const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports
type ExtractState<S> = S extends { getState: () => infer T } ? T : never
type WithReact<S extends StoreApi<unknown>> = S & {
getServerState?: () => ExtractState<S>
}
export function useStore<S extends WithReact<StoreApi<unknown>>>(
api: S
): ExtractState<S>
export function useStore<S extends WithReact<StoreApi<unknown>>, U>(
api: S,
selector: (state: ExtractState<S>) => U,
equalityFn?: (a: U, b: U) => boolean
): U
export function useStore<TState, StateSlice>(
api: WithReact<StoreApi<TState>>,
selector: (state: TState) => StateSlice = api.getState as any,
equalityFn?: (a: StateSlice, b: StateSlice) => boolean
) {
const slice = useSyncExternalStoreWithSelector(
api.subscribe,
api.getState,
api.getServerState || api.getState,
selector,
equalityFn
)
useDebugValue(slice)
return slice
}
export type UseBoundStore<S extends WithReact<StoreApi<unknown>>> = {
(): ExtractState<S>
<U>(
selector: (state: ExtractState<S>) => U,
equals?: (a: U, b: U) => boolean
): U
} & S
type Create = {
<T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
): UseBoundStore<Mutate<StoreApi<T>, Mos>>
<T>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
) => UseBoundStore<Mutate<StoreApi<T>, Mos>>
/**
* @deprecated Use `useStore` hook to bind store
*/
<S extends StoreApi<unknown>>(store: S): UseBoundStore<S>
}
const createImpl = <T>(createState: StateCreator<T, [], []>) => {
if (__DEV__ && typeof createState !== 'function') {
console.warn(
'[DEPRECATED] Passing a vanilla store will be unsupported in the future version. Please use `import { useStore } from "zustand"` to use the vanilla store in React.'
)
}
const api =
typeof createState === 'function' ? createStore(createState) : createState
const useBoundStore: any = (selector?: any, equalityFn?: any) =>
useStore(api, selector, equalityFn)
Object.assign(useBoundStore, api)
return useBoundStore
}
export const create = (<T>(createState: StateCreator<T, [], []> | undefined) =>
createState ? createImpl(createState) : createImpl) as Create
/**
* @deprecated Use `import { create } from 'zustand'`
*/
export default ((createState: any) => {
if (__DEV__) {
console.warn(
"[DEPRECATED] default export is deprecated, instead import { create } from'zustand'"
)
}
return create(createState)
}) as Create