Skip to content

Commit

Permalink
memo get(server)snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Jan 20, 2024
1 parent 46ee01f commit 9823aa5
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/react.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,31 @@ import type {
StoreMutatorIdentifier,
} from './vanilla.ts'

const { useDebugValue, useSyncExternalStore } = ReactExports
const { useDebugValue, useMemo, useSyncExternalStore } = ReactExports

type ExtractState<S> = S extends { getState: () => infer T } ? T : never

type ReadonlyStoreApi<T> = Pick<StoreApi<T>, 'getState' | 'subscribe'>

const identity = <T>(arg: T): T => arg

const useMemoSelector = <TState, StateSlice>(
getState: () => TState,
selector: (state: TState) => StateSlice,
) =>
useMemo(() => {
let lastSlice: StateSlice
let lastState: TState
return () => {
const state = getState()
if (!Object.is(lastState, state)) {
lastSlice = selector(state)
lastState = state
}
return lastSlice
}
}, [getState, selector])

export function useStore<S extends StoreApi<unknown>>(api: S): ExtractState<S>

export function useStore<S extends StoreApi<unknown>, U>(
Expand All @@ -33,8 +50,8 @@ export function useStore<TState, StateSlice>(
) {
const slice = useSyncExternalStore(
api.subscribe,
() => selector(api.getState()),
() => selector(api.getInitialState()),
useMemoSelector(api.getState, selector),
useMemoSelector(api.getInitialState, selector),
)
useDebugValue(slice)
return slice
Expand Down

0 comments on commit 9823aa5

Please sign in to comment.