mirror of
https://github.com/pmndrs/zustand.git
synced 2025-12-08 19:45:52 +00:00
Add optional dependencies for selector
This commit is contained in:
parent
9f2dfedf70
commit
1b6dae9fe5
19
src/index.ts
19
src/index.ts
@ -36,14 +36,23 @@ export default function create<
|
||||
}
|
||||
|
||||
function useStore(): State
|
||||
function useStore<U>(selector: StateSelector<State, U>): U
|
||||
function useStore<U>(selector?: StateSelector<State, U>) {
|
||||
function useStore<U>(
|
||||
selector: StateSelector<State, U>,
|
||||
deps?: readonly any[]
|
||||
): U
|
||||
function useStore<U>(
|
||||
selector?: StateSelector<State, U>,
|
||||
deps?: readonly any[]
|
||||
) {
|
||||
// Gets entire state if no selector was passed in
|
||||
const selectState = typeof selector === 'function' ? selector : getState
|
||||
const selectState = React.useCallback(
|
||||
typeof selector === 'function' ? selector : getState,
|
||||
deps as readonly any[]
|
||||
)
|
||||
// Nothing stored in useState, just using to enable forcing an update
|
||||
const [, forceUpdate] = React.useState({})
|
||||
// Always get latest slice because selector can change
|
||||
const stateSlice = selectState(state)
|
||||
// Always get latest slice unless dependencies are passed in
|
||||
const stateSlice = React.useMemo(() => selectState(state), deps)
|
||||
// Prevent subscribing/unsubscribing to the store when values change by storing them in a ref object
|
||||
const refs = React.useRef({ stateSlice, selectState }).current
|
||||
|
||||
|
||||
@ -160,3 +160,24 @@ it('can update the selector even when the store does not change', async () => {
|
||||
rerender(<Component selector={s => s.two} />)
|
||||
await waitForElement(() => getByText('two'))
|
||||
})
|
||||
|
||||
it('can pass optional dependencies to restrict selector calls', async () => {
|
||||
const [useStore] = create(() => ({}))
|
||||
let selectorCallCount = 0
|
||||
|
||||
function Component({ deps }) {
|
||||
useStore(() => {
|
||||
selectorCallCount++
|
||||
}, deps)
|
||||
return <div>{selectorCallCount}</div>
|
||||
}
|
||||
|
||||
const { rerender } = render(<Component deps={[true]} />)
|
||||
expect(selectorCallCount).toBe(1)
|
||||
|
||||
rerender(<Component deps={[true]} />)
|
||||
expect(selectorCallCount).toBe(1)
|
||||
|
||||
rerender(<Component deps={[false]} />)
|
||||
expect(selectorCallCount).toBe(2)
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user