mirror of
https://github.com/pmndrs/zustand.git
synced 2025-12-08 19:45:52 +00:00
fix(docs): useBoundStore instead of useStore (#1125)
* fix(docs): useBoundStore instead of useStore * run prettier
This commit is contained in:
parent
f07276c3f5
commit
fa581ddd9b
@ -39,7 +39,7 @@ interface BearState {
|
||||
increment: () => void
|
||||
}
|
||||
|
||||
const useStoreBase = create<BearState>()((set) => ({
|
||||
const useBearStoreBase = create<BearState>()((set) => ({
|
||||
bears: 0,
|
||||
increase: (by) => set((state) => ({ bears: state.bears + by })),
|
||||
increment: () => set((state) => ({ bears: state.bears + 1 })),
|
||||
@ -49,17 +49,17 @@ const useStoreBase = create<BearState>()((set) => ({
|
||||
## Apply that function to your store:
|
||||
|
||||
```typescript
|
||||
const useStore = createSelectors(useStoreBase)
|
||||
const useBearStore = createSelectors(useBearStoreBase)
|
||||
```
|
||||
|
||||
## Now the selectors are auto generated:
|
||||
|
||||
```typescript
|
||||
// get the property
|
||||
const bears = useStore.use.bears()
|
||||
const bears = useBearStore.use.bears()
|
||||
|
||||
// get the action
|
||||
const increase = useStore.use.increment()
|
||||
const increase = useBearStore.use.increment()
|
||||
```
|
||||
|
||||
## Live Demo
|
||||
|
||||
@ -6,14 +6,14 @@ In order to fix this, the action needs to be wrapped in `unstable_batchedUpdates
|
||||
```jsx
|
||||
import { unstable_batchedUpdates } from 'react-dom' // or 'react-native'
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useFishStore = create((set) => ({
|
||||
fishes: 0,
|
||||
increaseFishes: () => set((prev) => ({ fishes: prev.fishes + 1 })),
|
||||
}))
|
||||
|
||||
const nonReactCallback = () => {
|
||||
unstable_batchedUpdates(() => {
|
||||
useStore.getState().increaseFishes()
|
||||
useFishStore.getState().increaseFishes()
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
@ -7,7 +7,7 @@ Although zustand is an unopinionated library, here's one of the recommended usag
|
||||
- Define dispatch functions at the root level of the store to update one or more store slices
|
||||
|
||||
```js
|
||||
const useStore = create((set) => ({
|
||||
const useBoundStore = create((set) => ({
|
||||
storeSliceA: ...,
|
||||
storeSliceB: ...,
|
||||
storeSliceC: ...,
|
||||
@ -34,12 +34,12 @@ const reducer = (state, { type, by = 1 }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useGrumpyStore = create((set) => ({
|
||||
grumpiness: 0,
|
||||
dispatch: (args) => set((state) => reducer(state, args)),
|
||||
}))
|
||||
|
||||
const dispatch = useStore((state) => state.dispatch)
|
||||
const dispatch = useGrumpyStore((state) => state.dispatch)
|
||||
dispatch({ type: types.increase, by: 2 })
|
||||
```
|
||||
|
||||
@ -48,7 +48,7 @@ Or, just use our redux-middleware. It wires up your main-reducer, sets initial s
|
||||
```typescript
|
||||
import { redux } from 'zustand/middleware'
|
||||
|
||||
const useStore = create(redux(reducer, initialState))
|
||||
const useReduxStore = create(redux(reducer, initialState))
|
||||
```
|
||||
|
||||
Another way to update the store could be in functions wrapping the state functions. These could also handle side-effects of actions, for example for HTTP-calls. For using Zustand in a none-reactive way see [the readme](https://github.com/pmndrs/zustand#readingwriting-state-and-reacting-to-changes-outside-of-components)
|
||||
|
||||
@ -11,7 +11,7 @@ Quick example:
|
||||
import create from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
|
||||
export const useStore = create(
|
||||
export const useFishStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
fishes: 0,
|
||||
@ -44,7 +44,7 @@ Simply pass a function that returns the storage you want to use.
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ...
|
||||
@ -78,7 +78,7 @@ Since the only way to store an object in a storage is via a string, you can use
|
||||
For example, if you want to store your state in base64:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ...
|
||||
@ -104,7 +104,7 @@ If you pass a custom serialize function, you will most likely need to pass a cus
|
||||
To continue the example above, you could deserialize the base64 value using the following:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ...
|
||||
@ -128,7 +128,7 @@ Enables you to omit some of the state's fields to be stored in the storage.
|
||||
You could omit multiple fields using the following:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
foo: 0,
|
||||
@ -148,7 +148,7 @@ export const useStore = create(
|
||||
Or you could allow only specific fields using the following:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
foo: 0,
|
||||
@ -171,7 +171,7 @@ This option enables you to pass a listener function that will be called when the
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ...
|
||||
@ -218,7 +218,7 @@ The migrate function takes the persisted state and the version number as argumen
|
||||
For instance, if you want to rename a field, you can use the following:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
newField: 0, // let's say this field was named otherwise in version 0
|
||||
@ -275,7 +275,7 @@ The shallow merge will erase the `baz` field from the `foo` object.
|
||||
One way to fix this would be to give a custom deep merge function:
|
||||
|
||||
```ts
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
foo: {
|
||||
@ -307,7 +307,7 @@ This method can you get the options of the middleware.
|
||||
For example, it can be used to obtain the storage name:
|
||||
|
||||
```ts
|
||||
useStore.persist.getOptions().name
|
||||
useBoundStore.persist.getOptions().name
|
||||
```
|
||||
|
||||
### `setOptions`
|
||||
@ -319,7 +319,7 @@ This method enables you to change the middleware options. Note that the new opti
|
||||
For instance, this can be used to change the storage name:
|
||||
|
||||
```ts
|
||||
useStore.persist.setOptions({
|
||||
useBoundStore.persist.setOptions({
|
||||
name: 'new-name',
|
||||
})
|
||||
```
|
||||
@ -327,7 +327,7 @@ useStore.persist.setOptions({
|
||||
Or even to change the storage engine:
|
||||
|
||||
```ts
|
||||
useStore.persist.setOptions({
|
||||
useBoundStore.persist.setOptions({
|
||||
getStorage: () => sessionStorage,
|
||||
})
|
||||
```
|
||||
@ -339,7 +339,7 @@ useStore.persist.setOptions({
|
||||
This can be used to fully clear the persisted value in the storage.
|
||||
|
||||
```ts
|
||||
useStore.persist.clearStorage()
|
||||
useBoundStore.persist.clearStorage()
|
||||
```
|
||||
|
||||
### `rehydrate`
|
||||
@ -350,17 +350,17 @@ In some cases, you might want to trigger a rehydration manually.
|
||||
This can be done by calling the `rehydrate` method.
|
||||
|
||||
```ts
|
||||
await useStore.persist.rehydrate()
|
||||
await useBoundStore.persist.rehydrate()
|
||||
```
|
||||
|
||||
### `hasHydrated`
|
||||
|
||||
> Schema: `() => boolean`
|
||||
|
||||
This is a non-reactive getter to know if the storage has been hydrated (note that this does update when calling `useStore.persist.rehydrate()`).
|
||||
This is a non-reactive getter to know if the storage has been hydrated (note that this does update when calling `useBoundStore.persist.rehydrate()`).
|
||||
|
||||
```ts
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore.persist.hasHydrated()
|
||||
```
|
||||
|
||||
### `onHydrate`
|
||||
@ -370,7 +370,7 @@ useStore.persist.hasHydrated()
|
||||
The given listener will be called when the hydration process starts.
|
||||
|
||||
```ts
|
||||
const unsub = useStore.persist.onHydrate((state) => {
|
||||
const unsub = useBoundStore.persist.onHydrate((state) => {
|
||||
console.log('hydration starts')
|
||||
})
|
||||
|
||||
@ -385,7 +385,7 @@ unsub()
|
||||
The given listener will be called when the hydration process ends.
|
||||
|
||||
```ts
|
||||
const unsub = useStore.persist.onFinishHydration((state) => {
|
||||
const unsub = useBoundStore.persist.onFinishHydration((state) => {
|
||||
console.log('hydration finished')
|
||||
})
|
||||
|
||||
@ -420,7 +420,7 @@ There's a fiew different ways to do this.
|
||||
You can use the `onRehydrateStorage` option to update a field in the store:
|
||||
|
||||
```ts
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
// ...
|
||||
@ -441,7 +441,7 @@ const useStore = create(
|
||||
);
|
||||
|
||||
export default function App() {
|
||||
const hasHydrated = useStore(state => state._hasHydrated);
|
||||
const hasHydrated = useBoundStore(state => state._hasHydrated);
|
||||
|
||||
if (!hasHydrated) {
|
||||
return <p>Loading...</p>
|
||||
@ -456,16 +456,16 @@ export default function App() {
|
||||
You can also create a custom `useHydration` hook:
|
||||
|
||||
```ts
|
||||
const useStore = create(persist(...))
|
||||
const useBoundStore = create(persist(...))
|
||||
|
||||
const useHydration = () => {
|
||||
const [hydrated, setHydrated] = useState(useStore.persist.hasHydrated)
|
||||
const [hydrated, setHydrated] = useState(useBoundStore.persist.hasHydrated)
|
||||
|
||||
useEffect(() => {
|
||||
const unsubHydrate = useStore.persist.onHydrate(() => setHydrated(false)) // Note: this is just in case you want to take into account manual rehydrations. You can remove this if you don't need it/don't want it.
|
||||
const unsubFinishHydration = useStore.persist.onFinishHydration(() => setHydrated(true))
|
||||
const unsubHydrate = useBoundStore.persist.onHydrate(() => setHydrated(false)) // Note: this is just in case you want to take into account manual rehydrations. You can remove this if you don't need it/don't want it.
|
||||
const unsubFinishHydration = useBoundStore.persist.onFinishHydration(() => setHydrated(true))
|
||||
|
||||
setHydrated(useStore.persist.hasHydrated())
|
||||
setHydrated(useBoundStore.persist.hasHydrated())
|
||||
|
||||
return () => {
|
||||
unsubHydrate()
|
||||
@ -502,7 +502,7 @@ const storage: StateStorage = {
|
||||
},
|
||||
}
|
||||
|
||||
export const useStore = create(
|
||||
export const useBoundStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
fishes: 0,
|
||||
@ -538,6 +538,6 @@ export const withStorageDOMEvents = (store: StoreWithPersist) => {
|
||||
}
|
||||
}
|
||||
|
||||
const useStore = create(persist(...))
|
||||
withStorageDOMEvents(useStore)
|
||||
const useBoundStore = create(persist(...))
|
||||
withStorageDOMEvents(useBoundStore)
|
||||
```
|
||||
|
||||
@ -12,7 +12,7 @@ interface BearState {
|
||||
increase: (by: number) => void
|
||||
}
|
||||
|
||||
const useStore = create<BearState>()((set) => ({
|
||||
const useBearStore = create<BearState>()((set) => ({
|
||||
bears: 0,
|
||||
increase: (by) => set((state) => ({ bears: state.bears + by })),
|
||||
}))
|
||||
@ -59,7 +59,7 @@ The thing is Zustand is lying in it's type, the simplest way to prove it by show
|
||||
```ts
|
||||
import create from 'zustand/vanilla'
|
||||
|
||||
const useStore = create<{ foo: number }>()((_, get) => ({
|
||||
const useBoundStore = create<{ foo: number }>()((_, get) => ({
|
||||
foo: get().foo,
|
||||
}))
|
||||
```
|
||||
@ -121,7 +121,7 @@ Alternatively you can also use `combine` which infers the state instead of you h
|
||||
import create from 'zustand'
|
||||
import { combine } from 'zustand/middleware'
|
||||
|
||||
const useStore = create(
|
||||
const useBearStore = create(
|
||||
combine({ bears: 0 }, (set) => ({
|
||||
increase: (by: number) => set((state) => ({ bears: state.bears + by })),
|
||||
}))
|
||||
@ -133,9 +133,9 @@ const useStore = create(
|
||||
|
||||
<br/>
|
||||
|
||||
We achieve the inference by lying a little in the types of `set`, `get` and `store` that you receive as parameters. The lie is that they're typed in a way as if the state is the first parameter only when in fact the state is the shallow-merge (`{ ...a, ...b }`) of both first parameter and the second parameter's return. So for example `get` from the second parameter has type `() => { bears: number }` and that's a lie as it should be `() => { bears: number, increase: (by: number) => void }`. And `useStore` still has the correct type, ie for example `useStore.getState` is typed as `() => { bears: number, increase: (by: number) => void }`.
|
||||
We achieve the inference by lying a little in the types of `set`, `get` and `store` that you receive as parameters. The lie is that they're typed in a way as if the state is the first parameter only when in fact the state is the shallow-merge (`{ ...a, ...b }`) of both first parameter and the second parameter's return. So for example `get` from the second parameter has type `() => { bears: number }` and that's a lie as it should be `() => { bears: number, increase: (by: number) => void }`. And `useBoundStore` still has the correct type, ie for example `useBoundStore.getState` is typed as `() => { bears: number, increase: (by: number) => void }`.
|
||||
|
||||
It's not a lie lie because `{ bears: number }` is still a subtype `{ bears: number, increase: (by: number) => void }`, so in most cases there won't be a problem. Just you have to be careful while using replace. For eg `set({ bears: 0 }, true)` would compile but will be unsound as it'll delete the `increase` function. (If you set from "outside" ie `useStore.setState({ bears: 0 }, true)` then it won't compile because the "outside" store knows that `increase` is missing.) Another instance where you should be careful you're doing `Object.keys`, `Object.keys(get())` will return `["bears", "increase"]` and not `["bears"]` (the return type of `get` can make you fall for this).
|
||||
It's not a lie lie because `{ bears: number }` is still a subtype `{ bears: number, increase: (by: number) => void }`, so in most cases there won't be a problem. Just you have to be careful while using replace. For eg `set({ bears: 0 }, true)` would compile but will be unsound as it'll delete the `increase` function. (If you set from "outside" ie `useBoundStore.setState({ bears: 0 }, true)` then it won't compile because the "outside" store knows that `increase` is missing.) Another instance where you should be careful you're doing `Object.keys`, `Object.keys(get())` will return `["bears", "increase"]` and not `["bears"]` (the return type of `get` can make you fall for this).
|
||||
|
||||
So `combine` trades-off a little type-safety for the convenience of not having to write a type for state. Hence you should use `combine` accordingly, usually it's not a big deal and it's okay to use it.
|
||||
|
||||
@ -156,7 +156,7 @@ interface BearState {
|
||||
increase: (by: number) => void
|
||||
}
|
||||
|
||||
const useStore = create<BearState>()(
|
||||
const useBearStore = create<BearState>()(
|
||||
devtools(
|
||||
persist((set) => ({
|
||||
bears: 0,
|
||||
@ -179,7 +179,7 @@ interface BearState {
|
||||
increase: (by: number) => void
|
||||
}
|
||||
|
||||
const useStore = create<BearState>()(
|
||||
const useBearStore = create<BearState>()(
|
||||
myMiddlewares((set) => ({
|
||||
bears: 0,
|
||||
increase: (by) => set((state) => ({ bears: state.bears + by })),
|
||||
@ -199,8 +199,8 @@ const foo = (f, bar) => (set, get, store) => {
|
||||
return f(set, get, store)
|
||||
}
|
||||
|
||||
const useStore = create(foo(() => ({ bears: 0 }), 'hello'))
|
||||
console.log(useStore.foo.toUpperCase())
|
||||
const useBearStore = create(foo(() => ({ bears: 0 }), 'hello'))
|
||||
console.log(useBearStore.foo.toUpperCase())
|
||||
```
|
||||
|
||||
Yes, if you didn't know Zustand middlewares do and are allowed to mutate the store. But how could we possibly encode the mutation on the type-level? That is to say how could do we type `foo` so that this code compiles?
|
||||
@ -251,7 +251,7 @@ type PopArgument<T extends (...a: never[]) => unknown> = T extends (
|
||||
|
||||
// ---
|
||||
|
||||
const useStore = create<BearState>()(
|
||||
const useBearStore = create<BearState>()(
|
||||
logger(
|
||||
(set) => ({
|
||||
bears: 0,
|
||||
@ -317,8 +317,8 @@ type Cast<T, U> = T extends U ? T : U
|
||||
|
||||
// ---
|
||||
|
||||
const useStore = create(foo(() => ({ bears: 0 }), 'hello'))
|
||||
console.log(useStore.foo.toUpperCase())
|
||||
const useBearStore = create(foo(() => ({ bears: 0 }), 'hello'))
|
||||
console.log(useBearStore.foo.toUpperCase())
|
||||
```
|
||||
|
||||
### `create` without curried workaround
|
||||
@ -333,7 +333,7 @@ interface BearState {
|
||||
increase: (by: number) => void
|
||||
}
|
||||
|
||||
const useStore = create<
|
||||
const useBearStore = create<
|
||||
BearState,
|
||||
[
|
||||
['zustand/persist', BearState],
|
||||
@ -380,7 +380,7 @@ const createFishSlice: StateCreator<
|
||||
addFish: () => set((state) => ({ fishes: state.fishes + 1 })),
|
||||
})
|
||||
|
||||
const useStore = create<BearSlice & FishSlice>()((...a) => ({
|
||||
const useBoundStore = create<BearSlice & FishSlice>()((...a) => ({
|
||||
...createBearSlice(...a),
|
||||
...createFishSlice(...a),
|
||||
}))
|
||||
|
||||
81
readme.md
81
readme.md
@ -27,7 +27,7 @@ Your store is a hook! You can put anything in it: primitives, objects, functions
|
||||
```jsx
|
||||
import create from 'zustand'
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useBearStore = create((set) => ({
|
||||
bears: 0,
|
||||
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
|
||||
removeAllBears: () => set({ bears: 0 }),
|
||||
@ -40,12 +40,12 @@ Use the hook anywhere, no providers needed. Select your state and the component
|
||||
|
||||
```jsx
|
||||
function BearCounter() {
|
||||
const bears = useStore((state) => state.bears)
|
||||
const bears = useBearStore((state) => state.bears)
|
||||
return <h1>{bears} around here ...</h1>
|
||||
}
|
||||
|
||||
function Controls() {
|
||||
const increasePopulation = useStore((state) => state.increasePopulation)
|
||||
const increasePopulation = useBearStore((state) => state.increasePopulation)
|
||||
return <button onClick={increasePopulation}>one up</button>
|
||||
}
|
||||
```
|
||||
@ -72,7 +72,7 @@ function Controls() {
|
||||
You can, but bear in mind that it will cause the component to update on every state change!
|
||||
|
||||
```jsx
|
||||
const state = useStore()
|
||||
const state = useBearStore()
|
||||
```
|
||||
|
||||
## Selecting multiple state slices
|
||||
@ -80,8 +80,8 @@ const state = useStore()
|
||||
It detects changes with strict-equality (old === new) by default, this is efficient for atomic state picks.
|
||||
|
||||
```jsx
|
||||
const nuts = useStore((state) => state.nuts)
|
||||
const honey = useStore((state) => state.honey)
|
||||
const nuts = useBearStore((state) => state.nuts)
|
||||
const honey = useBearStore((state) => state.honey)
|
||||
```
|
||||
|
||||
If you want to construct a single object with multiple state-picks inside, similar to redux's mapStateToProps, you can tell zustand that you want the object to be diffed shallowly by passing the `shallow` equality function.
|
||||
@ -90,22 +90,25 @@ If you want to construct a single object with multiple state-picks inside, simil
|
||||
import shallow from 'zustand/shallow'
|
||||
|
||||
// Object pick, re-renders the component when either state.nuts or state.honey change
|
||||
const { nuts, honey } = useStore(
|
||||
const { nuts, honey } = useBearStore(
|
||||
(state) => ({ nuts: state.nuts, honey: state.honey }),
|
||||
shallow
|
||||
)
|
||||
|
||||
// Array pick, re-renders the component when either state.nuts or state.honey change
|
||||
const [nuts, honey] = useStore((state) => [state.nuts, state.honey], shallow)
|
||||
const [nuts, honey] = useBearStore(
|
||||
(state) => [state.nuts, state.honey],
|
||||
shallow
|
||||
)
|
||||
|
||||
// Mapped picks, re-renders the component when state.treats changes in order, count or keys
|
||||
const treats = useStore((state) => Object.keys(state.treats), shallow)
|
||||
const treats = useBearStore((state) => Object.keys(state.treats), shallow)
|
||||
```
|
||||
|
||||
For more control over re-rendering, you may provide any custom equality function.
|
||||
|
||||
```jsx
|
||||
const treats = useStore(
|
||||
const treats = useBearStore(
|
||||
(state) => state.treats,
|
||||
(oldTreats, newTreats) => compare(oldTreats, newTreats)
|
||||
)
|
||||
@ -118,7 +121,7 @@ The `set` function has a second argument, `false` by default. Instead of merging
|
||||
```jsx
|
||||
import omit from 'lodash-es/omit'
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useFishStore = create((set) => ({
|
||||
salmon: 1,
|
||||
tuna: 2,
|
||||
deleteEverything: () => set({}, true), // clears the entire store, actions included
|
||||
@ -131,7 +134,7 @@ const useStore = create((set) => ({
|
||||
Just call `set` when you're ready, zustand doesn't care if your actions are async or not.
|
||||
|
||||
```jsx
|
||||
const useStore = create((set) => ({
|
||||
const useFishStore = create((set) => ({
|
||||
fishies: {},
|
||||
fetch: async (pond) => {
|
||||
const response = await fetch(pond)
|
||||
@ -145,7 +148,7 @@ const useStore = create((set) => ({
|
||||
`set` allows fn-updates `set(state => result)`, but you still have access to state outside of it through `get`.
|
||||
|
||||
```jsx
|
||||
const useStore = create((set, get) => ({
|
||||
const useSoundStore = create((set, get) => ({
|
||||
sound: "grunt",
|
||||
action: () => {
|
||||
const sound = get().sound
|
||||
@ -159,22 +162,22 @@ const useStore = create((set, get) => ({
|
||||
Sometimes you need to access state in a non-reactive way, or act upon the store. For these cases the resulting hook has utility functions attached to its prototype.
|
||||
|
||||
```jsx
|
||||
const useStore = create(() => ({ paw: true, snout: true, fur: true }))
|
||||
const useDogStore = create(() => ({ paw: true, snout: true, fur: true }))
|
||||
|
||||
// Getting non-reactive fresh state
|
||||
const paw = useStore.getState().paw
|
||||
const paw = useDogStore.getState().paw
|
||||
// Listening to all changes, fires synchronously on every change
|
||||
const unsub1 = useStore.subscribe(console.log)
|
||||
const unsub1 = useDogStore.subscribe(console.log)
|
||||
// Updating state, will trigger listeners
|
||||
useStore.setState({ paw: false })
|
||||
useDogStore.setState({ paw: false })
|
||||
// Unsubscribe listeners
|
||||
unsub1()
|
||||
// Destroying the store (removing all listeners)
|
||||
useStore.destroy()
|
||||
useDogStore.destroy()
|
||||
|
||||
// You can of course use the hook as you always would
|
||||
const Component = () => {
|
||||
const paw = useStore((state) => state.paw)
|
||||
const paw = useDogStore((state) => state.paw)
|
||||
...
|
||||
```
|
||||
|
||||
@ -191,25 +194,25 @@ subscribe(selector, callback, options?: { equalityFn, fireImmediately }): Unsubs
|
||||
|
||||
```js
|
||||
import { subscribeWithSelector } from 'zustand/middleware'
|
||||
const useStore = create(
|
||||
const useDogStore = create(
|
||||
subscribeWithSelector(() => ({ paw: true, snout: true, fur: true }))
|
||||
)
|
||||
|
||||
// Listening to selected changes, in this case when "paw" changes
|
||||
const unsub2 = useStore.subscribe((state) => state.paw, console.log)
|
||||
const unsub2 = useDogStore.subscribe((state) => state.paw, console.log)
|
||||
// Subscribe also exposes the previous value
|
||||
const unsub3 = useStore.subscribe(
|
||||
const unsub3 = useDogStore.subscribe(
|
||||
(state) => state.paw,
|
||||
(paw, previousPaw) => console.log(paw, previousPaw)
|
||||
)
|
||||
// Subscribe also supports an optional equality function
|
||||
const unsub4 = useStore.subscribe(
|
||||
const unsub4 = useDogStore.subscribe(
|
||||
(state) => [state.paw, state.fur],
|
||||
console.log,
|
||||
{ equalityFn: shallow }
|
||||
)
|
||||
// Subscribe and fire immediately
|
||||
const unsub5 = useStore.subscribe((state) => state.paw, console.log, {
|
||||
const unsub5 = useDogStore.subscribe((state) => state.paw, console.log, {
|
||||
fireImmediately: true,
|
||||
})
|
||||
```
|
||||
@ -231,7 +234,7 @@ You can even consume an existing vanilla store with React:
|
||||
import create from 'zustand'
|
||||
import vanillaStore from './vanillaStore'
|
||||
|
||||
const useStore = create(vanillaStore)
|
||||
const useBoundStore = create(vanillaStore)
|
||||
```
|
||||
|
||||
:warning: Note that middlewares that modify `set` or `get` are not applied to `getState` and `setState`.
|
||||
@ -241,13 +244,13 @@ const useStore = create(vanillaStore)
|
||||
The subscribe function allows components to bind to a state-portion without forcing re-render on changes. Best combine it with useEffect for automatic unsubscribe on unmount. This can make a [drastic](https://codesandbox.io/s/peaceful-johnson-txtws) performance impact when you are allowed to mutate the view directly.
|
||||
|
||||
```jsx
|
||||
const useStore = create(set => ({ scratches: 0, ... }))
|
||||
const useScratchStore = create(set => ({ scratches: 0, ... }))
|
||||
|
||||
const Component = () => {
|
||||
// Fetch initial state
|
||||
const scratchRef = useRef(useStore.getState().scratches)
|
||||
const scratchRef = useRef(useScratchStore.getState().scratches)
|
||||
// Connect to the store on mount, disconnect on unmount, catch state-changes in a reference
|
||||
useEffect(() => useStore.subscribe(
|
||||
useEffect(() => useScratchStore.subscribe(
|
||||
state => (scratchRef.current = state.scratches)
|
||||
), [])
|
||||
...
|
||||
@ -260,7 +263,7 @@ Reducing nested structures is tiresome. Have you tried [immer](https://github.co
|
||||
```jsx
|
||||
import produce from 'immer'
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useLushStore = create((set) => ({
|
||||
lush: { forest: { contains: { a: 'bear' } } },
|
||||
clearForest: () =>
|
||||
set(
|
||||
@ -270,7 +273,7 @@ const useStore = create((set) => ({
|
||||
),
|
||||
}))
|
||||
|
||||
const clearForest = useStore((state) => state.clearForest)
|
||||
const clearForest = useLushStore((state) => state.clearForest)
|
||||
clearForest()
|
||||
```
|
||||
|
||||
@ -293,7 +296,7 @@ const log = (config) => (set, get, api) =>
|
||||
api
|
||||
)
|
||||
|
||||
const useStore = create(
|
||||
const useBeeStore = create(
|
||||
log((set) => ({
|
||||
bees: false,
|
||||
setBees: (input) => set({ bees: input }),
|
||||
@ -309,7 +312,7 @@ You can persist your store's data using any kind of storage.
|
||||
import create from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
|
||||
const useStore = create(
|
||||
const useFishStore = create(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
fishes: 0,
|
||||
@ -333,7 +336,7 @@ Immer is available as middleware too.
|
||||
import create from 'zustand'
|
||||
import { immer } from 'zustand/middleware/immer'
|
||||
|
||||
const useStore = create(
|
||||
const useBeeStore = create(
|
||||
immer((set) => ({
|
||||
bees: 0,
|
||||
addBees: (by) =>
|
||||
@ -358,12 +361,12 @@ const reducer = (state, { type, by = 1 }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const useStore = create((set) => ({
|
||||
const useGrumpyStore = create((set) => ({
|
||||
grumpiness: 0,
|
||||
dispatch: (args) => set((state) => reducer(state, args)),
|
||||
}))
|
||||
|
||||
const dispatch = useStore((state) => state.dispatch)
|
||||
const dispatch = useGrumpyStore((state) => state.dispatch)
|
||||
dispatch({ type: types.increase, by: 2 })
|
||||
```
|
||||
|
||||
@ -372,7 +375,7 @@ Or, just use our redux-middleware. It wires up your main-reducer, sets initial s
|
||||
```jsx
|
||||
import { redux } from 'zustand/middleware'
|
||||
|
||||
const useStore = create(redux(reducer, initialState))
|
||||
const useGrumpyStore = create(redux(reducer, initialState))
|
||||
```
|
||||
|
||||
## Redux devtools
|
||||
@ -381,9 +384,9 @@ const useStore = create(redux(reducer, initialState))
|
||||
import { devtools } from 'zustand/middleware'
|
||||
|
||||
// Usage with a plain action store, it will log actions as "setState"
|
||||
const useStore = create(devtools(store))
|
||||
const usePlainStore = create(devtools(store))
|
||||
// Usage with a redux store, it will log full action types
|
||||
const useStore = create(devtools(redux(reducer, initialState)))
|
||||
const useReduxStore = create(devtools(redux(reducer, initialState)))
|
||||
```
|
||||
|
||||
devtools takes the store function as its first argument, optionally you can name the store or configure [serialize](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md#serialize) options with a second argument.
|
||||
@ -558,7 +561,7 @@ interface BearState {
|
||||
increase: (by: number) => void
|
||||
}
|
||||
|
||||
const useStore = create<BearState>()(
|
||||
const useBearStore = create<BearState>()(
|
||||
devtools(
|
||||
persist((set) => ({
|
||||
bears: 0,
|
||||
|
||||
@ -43,13 +43,13 @@ type CounterState = {
|
||||
}
|
||||
|
||||
it('uses the store with no args', async () => {
|
||||
const useStore = create<CounterState>((set) => ({
|
||||
const useBoundStore = create<CounterState>((set) => ({
|
||||
count: 0,
|
||||
inc: () => set((state) => ({ count: state.count + 1 })),
|
||||
}))
|
||||
|
||||
function Counter() {
|
||||
const { count, inc } = useStore()
|
||||
const { count, inc } = useBoundStore()
|
||||
useEffect(inc, [inc])
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
@ -60,14 +60,14 @@ it('uses the store with no args', async () => {
|
||||
})
|
||||
|
||||
it('uses the store with selectors', async () => {
|
||||
const useStore = create<CounterState>((set) => ({
|
||||
const useBoundStore = create<CounterState>((set) => ({
|
||||
count: 0,
|
||||
inc: () => set((state) => ({ count: state.count + 1 })),
|
||||
}))
|
||||
|
||||
function Counter() {
|
||||
const count = useStore((s) => s.count)
|
||||
const inc = useStore((s) => s.inc)
|
||||
const count = useBoundStore((s) => s.count)
|
||||
const inc = useBoundStore((s) => s.inc)
|
||||
useEffect(inc, [inc])
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
@ -78,13 +78,13 @@ it('uses the store with selectors', async () => {
|
||||
})
|
||||
|
||||
it('uses the store with a selector and equality checker', async () => {
|
||||
const useStore = create(() => ({ item: { value: 0 } }))
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create(() => ({ item: { value: 0 } }))
|
||||
const { setState } = useBoundStore
|
||||
let renderCount = 0
|
||||
|
||||
function Component() {
|
||||
// Prevent re-render if new value === 1.
|
||||
const item = useStore(
|
||||
const item = useBoundStore(
|
||||
(s) => s.item,
|
||||
(_, newItem) => newItem.value === 1
|
||||
)
|
||||
@ -109,7 +109,7 @@ it('uses the store with a selector and equality checker', async () => {
|
||||
})
|
||||
|
||||
it('only re-renders if selected state has changed', async () => {
|
||||
const useStore = create<CounterState>((set) => ({
|
||||
const useBoundStore = create<CounterState>((set) => ({
|
||||
count: 0,
|
||||
inc: () => set((state) => ({ count: state.count + 1 })),
|
||||
}))
|
||||
@ -117,13 +117,13 @@ it('only re-renders if selected state has changed', async () => {
|
||||
let controlRenderCount = 0
|
||||
|
||||
function Counter() {
|
||||
const count = useStore((state) => state.count)
|
||||
const count = useBoundStore((state) => state.count)
|
||||
counterRenderCount++
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
function Control() {
|
||||
const inc = useStore((state) => state.inc)
|
||||
const inc = useBoundStore((state) => state.inc)
|
||||
controlRenderCount++
|
||||
return <button onClick={inc}>button</button>
|
||||
}
|
||||
@ -144,12 +144,12 @@ it('only re-renders if selected state has changed', async () => {
|
||||
})
|
||||
|
||||
it('re-renders with useLayoutEffect', async () => {
|
||||
const useStore = create(() => ({ state: false }))
|
||||
const useBoundStore = create(() => ({ state: false }))
|
||||
|
||||
function Component() {
|
||||
const { state } = useStore()
|
||||
const { state } = useBoundStore()
|
||||
useLayoutEffect(() => {
|
||||
useStore.setState({ state: true })
|
||||
useBoundStore.setState({ state: true })
|
||||
}, [])
|
||||
return <>{`${state}`}</>
|
||||
}
|
||||
@ -163,13 +163,13 @@ it('re-renders with useLayoutEffect', async () => {
|
||||
})
|
||||
|
||||
it('can batch updates', async () => {
|
||||
const useStore = create<CounterState>((set) => ({
|
||||
const useBoundStore = create<CounterState>((set) => ({
|
||||
count: 0,
|
||||
inc: () => set((state) => ({ count: state.count + 1 })),
|
||||
}))
|
||||
|
||||
function Counter() {
|
||||
const { count, inc } = useStore()
|
||||
const { count, inc } = useBoundStore()
|
||||
useEffect(() => {
|
||||
ReactDOM.unstable_batchedUpdates(() => {
|
||||
inc()
|
||||
@ -187,13 +187,13 @@ it('can batch updates', async () => {
|
||||
it('can update the selector', async () => {
|
||||
type State = { one: string; two: string }
|
||||
type Props = { selector: (state: State) => string }
|
||||
const useStore = create<State>(() => ({
|
||||
const useBoundStore = create<State>(() => ({
|
||||
one: 'one',
|
||||
two: 'two',
|
||||
}))
|
||||
|
||||
function Component({ selector }: Props) {
|
||||
return <div>{useStore(selector)}</div>
|
||||
return <div>{useBoundStore(selector)}</div>
|
||||
}
|
||||
|
||||
const { findByText, rerender } = render(<Component selector={(s) => s.one} />)
|
||||
@ -206,13 +206,13 @@ it('can update the selector', async () => {
|
||||
it('can update the equality checker', async () => {
|
||||
type State = { value: number }
|
||||
type Props = { equalityFn: (a: State, b: State) => boolean }
|
||||
const useStore = create<State>(() => ({ value: 0 }))
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create<State>(() => ({ value: 0 }))
|
||||
const { setState } = useBoundStore
|
||||
const selector = (s: State) => s
|
||||
|
||||
let renderCount = 0
|
||||
function Component({ equalityFn }: Props) {
|
||||
const { value } = useStore(selector, equalityFn)
|
||||
const { value } = useBoundStore(selector, equalityFn)
|
||||
return (
|
||||
<div>
|
||||
renderCount: {++renderCount}, value: {value}
|
||||
@ -237,19 +237,19 @@ it('can update the equality checker', async () => {
|
||||
await findByText('renderCount: 3, value: 0')
|
||||
})
|
||||
|
||||
it('can call useStore with progressively more arguments', async () => {
|
||||
it('can call useBoundStore with progressively more arguments', async () => {
|
||||
type State = { value: number }
|
||||
type Props = {
|
||||
selector?: (state: State) => number
|
||||
equalityFn?: (a: number, b: number) => boolean
|
||||
}
|
||||
|
||||
const useStore = create<State>(() => ({ value: 0 }))
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create<State>(() => ({ value: 0 }))
|
||||
const { setState } = useBoundStore
|
||||
|
||||
let renderCount = 0
|
||||
function Component({ selector, equalityFn }: Props) {
|
||||
const value = useStore(selector as any, equalityFn)
|
||||
const value = useBoundStore(selector as any, equalityFn)
|
||||
return (
|
||||
<div>
|
||||
renderCount: {++renderCount}, value: {JSON.stringify(value)}
|
||||
@ -286,8 +286,8 @@ it('can throw an error in selector', async () => {
|
||||
type State = { value: string | number }
|
||||
|
||||
const initialState: State = { value: 'foo' }
|
||||
const useStore = create<State>(() => initialState)
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create<State>(() => initialState)
|
||||
const { setState } = useBoundStore
|
||||
const selector = (s: State) =>
|
||||
// @ts-expect-error This function is supposed to throw an error
|
||||
s.value.toUpperCase()
|
||||
@ -309,7 +309,7 @@ it('can throw an error in selector', async () => {
|
||||
}
|
||||
|
||||
function Component() {
|
||||
useStore(selector)
|
||||
useBoundStore(selector)
|
||||
return <div>no error</div>
|
||||
}
|
||||
|
||||
@ -331,8 +331,8 @@ it('can throw an error in equality checker', async () => {
|
||||
type State = { value: string | number }
|
||||
|
||||
const initialState: State = { value: 'foo' }
|
||||
const useStore = create(() => initialState)
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create(() => initialState)
|
||||
const { setState } = useBoundStore
|
||||
const selector = (s: State) => s
|
||||
const equalityFn = (a: State, b: State) =>
|
||||
// @ts-expect-error This function is supposed to throw an error
|
||||
@ -355,7 +355,7 @@ it('can throw an error in equality checker', async () => {
|
||||
}
|
||||
|
||||
function Component() {
|
||||
useStore(selector, equalityFn)
|
||||
useBoundStore(selector, equalityFn)
|
||||
return <div>no error</div>
|
||||
}
|
||||
|
||||
@ -439,8 +439,8 @@ it('can destroy the store', () => {
|
||||
|
||||
it('only calls selectors when necessary', async () => {
|
||||
type State = { a: number; b: number }
|
||||
const useStore = create<State>(() => ({ a: 0, b: 0 }))
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create<State>(() => ({ a: 0, b: 0 }))
|
||||
const { setState } = useBoundStore
|
||||
let inlineSelectorCallCount = 0
|
||||
let staticSelectorCallCount = 0
|
||||
|
||||
@ -450,8 +450,8 @@ it('only calls selectors when necessary', async () => {
|
||||
}
|
||||
|
||||
function Component() {
|
||||
useStore((s) => (inlineSelectorCallCount++, s.b))
|
||||
useStore(staticSelector)
|
||||
useBoundStore((s) => (inlineSelectorCallCount++, s.b))
|
||||
useBoundStore(staticSelector)
|
||||
return (
|
||||
<>
|
||||
<div>inline: {inlineSelectorCallCount}</div>
|
||||
@ -478,13 +478,13 @@ it('ensures parent components subscribe before children', async () => {
|
||||
children: { [key: string]: { text: string } }
|
||||
}
|
||||
type Props = { id: string }
|
||||
const useStore = create<State>(() => ({
|
||||
const useBoundStore = create<State>(() => ({
|
||||
children: {
|
||||
'1': { text: 'child 1' },
|
||||
'2': { text: 'child 2' },
|
||||
},
|
||||
}))
|
||||
const api = useStore
|
||||
const api = useBoundStore
|
||||
|
||||
function changeState() {
|
||||
api.setState({
|
||||
@ -495,12 +495,12 @@ it('ensures parent components subscribe before children', async () => {
|
||||
}
|
||||
|
||||
function Child({ id }: Props) {
|
||||
const text = useStore((s) => s.children[id]?.text)
|
||||
const text = useBoundStore((s) => s.children[id]?.text)
|
||||
return <div>{text}</div>
|
||||
}
|
||||
|
||||
function Parent() {
|
||||
const childStates = useStore((s) => s.children)
|
||||
const childStates = useBoundStore((s) => s.children)
|
||||
return (
|
||||
<>
|
||||
<button onClick={changeState}>change state</button>
|
||||
@ -520,15 +520,15 @@ it('ensures parent components subscribe before children', async () => {
|
||||
|
||||
// https://github.com/pmndrs/zustand/issues/84
|
||||
it('ensures the correct subscriber is removed on unmount', async () => {
|
||||
const useStore = create(() => ({ count: 0 }))
|
||||
const api = useStore
|
||||
const useBoundStore = create(() => ({ count: 0 }))
|
||||
const api = useBoundStore
|
||||
|
||||
function increment() {
|
||||
api.setState(({ count }) => ({ count: count + 1 }))
|
||||
}
|
||||
|
||||
function Count() {
|
||||
const c = useStore((s) => s.count)
|
||||
const c = useBoundStore((s) => s.count)
|
||||
return <div>count: {c}</div>
|
||||
}
|
||||
|
||||
@ -561,16 +561,16 @@ it('ensures the correct subscriber is removed on unmount', async () => {
|
||||
|
||||
// https://github.com/pmndrs/zustand/issues/86
|
||||
it('ensures a subscriber is not mistakenly overwritten', async () => {
|
||||
const useStore = create(() => ({ count: 0 }))
|
||||
const { setState } = useStore
|
||||
const useBoundStore = create(() => ({ count: 0 }))
|
||||
const { setState } = useBoundStore
|
||||
|
||||
function Count1() {
|
||||
const c = useStore((s) => s.count)
|
||||
const c = useBoundStore((s) => s.count)
|
||||
return <div>count1: {c}</div>
|
||||
}
|
||||
|
||||
function Count2() {
|
||||
const c = useStore((s) => s.count)
|
||||
const c = useBoundStore((s) => s.count)
|
||||
return <div>count2: {c}</div>
|
||||
}
|
||||
|
||||
|
||||
@ -16,17 +16,17 @@ type CounterState = {
|
||||
|
||||
describe('counter state spec (no middleware)', () => {
|
||||
it('no middleware', () => {
|
||||
const useStore = create<CounterState>((set, get) => ({
|
||||
const useBoundStore = create<CounterState>((set, get) => ({
|
||||
count: 0,
|
||||
inc: () => set({ count: get().count + 1 }, false),
|
||||
}))
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -43,7 +43,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('immer', () => {
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
immer((set, get) => ({
|
||||
count: 0,
|
||||
inc: () =>
|
||||
@ -53,12 +53,12 @@ describe('counter state spec (single middleware)', () => {
|
||||
}))
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -69,7 +69,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('redux', () => {
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
redux<{ count: number }, { type: 'INC' }>(
|
||||
(state, action) => {
|
||||
switch (action.type) {
|
||||
@ -83,10 +83,10 @@ describe('counter state spec (single middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.dispatch)({ type: 'INC' })
|
||||
useStore().dispatch({ type: 'INC' })
|
||||
useStore.dispatch({ type: 'INC' })
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.dispatch)({ type: 'INC' })
|
||||
useBoundStore().dispatch({ type: 'INC' })
|
||||
useBoundStore.dispatch({ type: 'INC' })
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -98,7 +98,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
|
||||
it('devtools', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
count: 0,
|
||||
@ -108,13 +108,13 @@ describe('counter state spec (single middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -125,20 +125,20 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('subscribeWithSelector', () => {
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
count: 1,
|
||||
inc: () => set({ count: get().count + 1 }, false),
|
||||
}))
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
@ -152,18 +152,18 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('combine', () => {
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
combine({ count: 1 }, (set, get) => ({
|
||||
inc: () => set({ count: get().count + 1 }, false),
|
||||
}))
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -174,7 +174,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('persist', () => {
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
count: 1,
|
||||
@ -184,13 +184,13 @@ describe('counter state spec (single middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -201,7 +201,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('persist with partialize', () => {
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
count: 1,
|
||||
@ -211,14 +211,14 @@ describe('counter state spec (single middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.persist.hasHydrated()
|
||||
useStore.persist.setOptions({
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.persist.hasHydrated()
|
||||
useBoundStore.persist.setOptions({
|
||||
// @ts-expect-error to test if the partialized state is inferred as number
|
||||
partialize: () => 'not-a-number',
|
||||
})
|
||||
@ -228,7 +228,7 @@ describe('counter state spec (single middleware)', () => {
|
||||
})
|
||||
|
||||
it('persist without custom api (#638)', () => {
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
count: 1,
|
||||
@ -238,12 +238,12 @@ describe('counter state spec (single middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -261,7 +261,7 @@ describe('counter state spec (double middleware)', () => {
|
||||
|
||||
it('devtools & immer', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
count: 0,
|
||||
@ -274,13 +274,13 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -288,7 +288,7 @@ describe('counter state spec (double middleware)', () => {
|
||||
|
||||
it('devtools & redux', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
devtools(
|
||||
redux(
|
||||
(state, action: { type: 'INC' }) => {
|
||||
@ -305,11 +305,11 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.dispatch)({ type: 'INC' })
|
||||
useStore().dispatch({ type: 'INC' })
|
||||
useStore.dispatch({ type: 'INC' })
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.dispatch)({ type: 'INC' })
|
||||
useBoundStore().dispatch({ type: 'INC' })
|
||||
useBoundStore.dispatch({ type: 'INC' })
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -317,7 +317,7 @@ describe('counter state spec (double middleware)', () => {
|
||||
|
||||
it('devtools & combine', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
devtools(
|
||||
combine({ count: 1 }, (set, get) => ({
|
||||
inc: () => set({ count: get().count + 1 }, false, 'inc'),
|
||||
@ -326,20 +326,20 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
})
|
||||
|
||||
it('subscribeWithSelector & combine', () => {
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
subscribeWithSelector(
|
||||
combine({ count: 1 }, (set, get) => ({
|
||||
inc: () => set({ count: get().count + 1 }, false),
|
||||
@ -347,13 +347,13 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
@ -364,7 +364,7 @@ describe('counter state spec (double middleware)', () => {
|
||||
|
||||
it('devtools & subscribeWithSelector', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
count: 1,
|
||||
@ -374,17 +374,17 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -392,7 +392,7 @@ describe('counter state spec (double middleware)', () => {
|
||||
|
||||
it('devtools & persist', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
@ -405,14 +405,14 @@ describe('counter state spec (double middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -430,7 +430,7 @@ describe('counter state spec (triple middleware)', () => {
|
||||
|
||||
it('devtools & persist & immer', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
@ -446,14 +446,14 @@ describe('counter state spec (triple middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -461,7 +461,7 @@ describe('counter state spec (triple middleware)', () => {
|
||||
|
||||
it('devtools & subscribeWithSelector & combine', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
devtools(
|
||||
subscribeWithSelector(
|
||||
combine({ count: 1 }, (set, get) => ({
|
||||
@ -472,17 +472,17 @@ describe('counter state spec (triple middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -490,7 +490,7 @@ describe('counter state spec (triple middleware)', () => {
|
||||
|
||||
it('devtools & subscribeWithSelector & persist', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
subscribeWithSelector(
|
||||
persist(
|
||||
@ -505,18 +505,18 @@ describe('counter state spec (triple middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -534,7 +534,7 @@ describe('counter state spec (quadruple middleware)', () => {
|
||||
|
||||
it('devtools & subscribeWithSelector & persist & immer (#616)', () => {
|
||||
__DEV__ = false
|
||||
const useStore = create<CounterState>()(
|
||||
const useBoundStore = create<CounterState>()(
|
||||
devtools(
|
||||
subscribeWithSelector(
|
||||
persist(
|
||||
@ -552,18 +552,18 @@ describe('counter state spec (quadruple middleware)', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
useStore.setState({ count: 0 }, false, 'reset')
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore.setState({ count: 0 }, false, 'reset')
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -572,7 +572,7 @@ describe('counter state spec (quadruple middleware)', () => {
|
||||
|
||||
describe('more complex state spec with subscribeWithSelector', () => {
|
||||
it('#619, #632', () => {
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
subscribeWithSelector(
|
||||
persist(
|
||||
() => ({
|
||||
@ -583,14 +583,14 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.foo)
|
||||
useStore().foo
|
||||
useStore.getState().foo
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.foo)
|
||||
useBoundStore().foo
|
||||
useBoundStore.getState().foo
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.foo,
|
||||
(foo) => console.log(foo)
|
||||
)
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -600,7 +600,7 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
type MyState = {
|
||||
foo: number | null
|
||||
}
|
||||
const useStore = create<MyState>()(
|
||||
const useBoundStore = create<MyState>()(
|
||||
subscribeWithSelector(
|
||||
() =>
|
||||
({
|
||||
@ -609,10 +609,10 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.foo)
|
||||
useStore().foo
|
||||
useStore.getState().foo
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.foo)
|
||||
useBoundStore().foo
|
||||
useBoundStore.getState().foo
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.foo,
|
||||
(foo) => console.log(foo)
|
||||
)
|
||||
@ -627,7 +627,7 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
authenticated: boolean
|
||||
authenticate: (username: string, password: string) => Promise<void>
|
||||
}
|
||||
const useStore = create<MyState>()(
|
||||
const useBoundStore = create<MyState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
token: undefined,
|
||||
@ -640,12 +640,12 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.authenticated)
|
||||
useStore((s) => s.authenticate)('u', 'p')
|
||||
useStore().authenticated
|
||||
useStore().authenticate('u', 'p')
|
||||
useStore.getState().authenticated
|
||||
useStore.getState().authenticate('u', 'p')
|
||||
useBoundStore((s) => s.authenticated)
|
||||
useBoundStore((s) => s.authenticate)('u', 'p')
|
||||
useBoundStore().authenticated
|
||||
useBoundStore().authenticate('u', 'p')
|
||||
useBoundStore.getState().authenticated
|
||||
useBoundStore.getState().authenticate('u', 'p')
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
@ -654,7 +654,7 @@ describe('more complex state spec with subscribeWithSelector', () => {
|
||||
|
||||
describe('create with explicitly annotated mutators', () => {
|
||||
it('subscribeWithSelector & persist', () => {
|
||||
const useStore = create<
|
||||
const useBoundStore = create<
|
||||
CounterState,
|
||||
[
|
||||
['zustand/subscribeWithSelector', never],
|
||||
@ -672,18 +672,18 @@ describe('create with explicitly annotated mutators', () => {
|
||||
)
|
||||
)
|
||||
const TestComponent = () => {
|
||||
useStore((s) => s.count) * 2
|
||||
useStore((s) => s.inc)()
|
||||
useStore().count * 2
|
||||
useStore().inc()
|
||||
useStore.getState().count * 2
|
||||
useStore.getState().inc()
|
||||
useStore.subscribe(
|
||||
useBoundStore((s) => s.count) * 2
|
||||
useBoundStore((s) => s.inc)()
|
||||
useBoundStore().count * 2
|
||||
useBoundStore().inc()
|
||||
useBoundStore.getState().count * 2
|
||||
useBoundStore.getState().inc()
|
||||
useBoundStore.subscribe(
|
||||
(state) => state.count,
|
||||
(count) => console.log(count * 2)
|
||||
)
|
||||
useStore.setState({ count: 0 }, false)
|
||||
useStore.persist.hasHydrated()
|
||||
useBoundStore.setState({ count: 0 }, false)
|
||||
useBoundStore.persist.hasHydrated()
|
||||
return <></>
|
||||
}
|
||||
TestComponent
|
||||
|
||||
@ -50,7 +50,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(
|
||||
() => ({
|
||||
count: 0,
|
||||
@ -65,7 +65,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count, name } = useStore()
|
||||
const { count, name } = useBoundStore()
|
||||
return (
|
||||
<div>
|
||||
count: {count}, name: {name}
|
||||
@ -94,7 +94,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -103,7 +103,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -123,21 +123,21 @@ describe('persist middleware with async configuration', () => {
|
||||
|
||||
const createStore = () => {
|
||||
const onRehydrateStorageSpy = jest.fn()
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
onRehydrateStorage: () => onRehydrateStorageSpy,
|
||||
})
|
||||
)
|
||||
return { useStore, onRehydrateStorageSpy }
|
||||
return { useBoundStore, onRehydrateStorageSpy }
|
||||
}
|
||||
|
||||
// Initialize from empty storage
|
||||
const { useStore, onRehydrateStorageSpy } = createStore()
|
||||
const { useBoundStore, onRehydrateStorageSpy } = createStore()
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ describe('persist middleware with async configuration', () => {
|
||||
})
|
||||
|
||||
// Write something to the store
|
||||
act(() => useStore.setState({ count: 42 }))
|
||||
act(() => useBoundStore.setState({ count: 42 }))
|
||||
await findByText('count: 42')
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage',
|
||||
@ -158,11 +158,11 @@ describe('persist middleware with async configuration', () => {
|
||||
// Create the same store a second time and check if the persisted state
|
||||
// is loaded correctly
|
||||
const {
|
||||
useStore: useStore2,
|
||||
useBoundStore: useBoundStore2,
|
||||
onRehydrateStorageSpy: onRehydrateStorageSpy2,
|
||||
} = createStore()
|
||||
function Counter2() {
|
||||
const { count } = useStore2()
|
||||
const { count } = useBoundStore2()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -199,7 +199,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create<{
|
||||
const useBoundStore = create<{
|
||||
count: number
|
||||
name: string
|
||||
setName: (name: string) => void
|
||||
@ -249,7 +249,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Component() {
|
||||
const { count, setName, name } = useStore()
|
||||
const { count, setName, name } = useBoundStore()
|
||||
useEffect(() => {
|
||||
setName('test')
|
||||
}, [setName])
|
||||
@ -266,7 +266,7 @@ describe('persist middleware with async configuration', () => {
|
||||
await findByText('count: 42')
|
||||
await findByText('name: test')
|
||||
|
||||
expect(useStore.getState()).toEqual(
|
||||
expect(useBoundStore.getState()).toEqual(
|
||||
expect.objectContaining({
|
||||
count: 42,
|
||||
name: 'test',
|
||||
@ -287,7 +287,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -297,7 +297,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -324,7 +324,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -337,7 +337,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -367,7 +367,7 @@ describe('persist middleware with async configuration', () => {
|
||||
|
||||
const unstorableMethod = () => {}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0, unstorableMethod }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -376,7 +376,7 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ describe('persist middleware with async configuration', () => {
|
||||
|
||||
const unstorableMethod = () => {}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0, actions: { unstorableMethod } }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -424,14 +424,14 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
const { findByText } = render(<Counter />)
|
||||
|
||||
await findByText('count: 1')
|
||||
expect(useStore.getState()).toEqual({
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
actions: {
|
||||
unstorableMethod,
|
||||
@ -451,7 +451,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -460,14 +460,14 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
function Counter() {
|
||||
const { count } = useStore()
|
||||
const { count } = useBoundStore()
|
||||
return <div>count: {count}</div>
|
||||
}
|
||||
|
||||
const { findByText } = render(<Counter />)
|
||||
|
||||
await findByText('count: 1')
|
||||
expect(useStore.getState()).toEqual({
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
})
|
||||
})
|
||||
@ -481,7 +481,7 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -489,8 +489,8 @@ describe('persist middleware with async configuration', () => {
|
||||
)
|
||||
|
||||
storage.getItem = async () => storageValue
|
||||
await useStore.persist.rehydrate()
|
||||
expect(useStore.getState()).toEqual({
|
||||
await useBoundStore.persist.rehydrate()
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
})
|
||||
})
|
||||
@ -502,17 +502,19 @@ describe('persist middleware with async configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
})
|
||||
)
|
||||
expect(useStore.persist.hasHydrated()).toBe(false)
|
||||
await new Promise((resolve) => useStore.persist.onFinishHydration(resolve))
|
||||
expect(useStore.persist.hasHydrated()).toBe(true)
|
||||
expect(useBoundStore.persist.hasHydrated()).toBe(false)
|
||||
await new Promise((resolve) =>
|
||||
useBoundStore.persist.onFinishHydration(resolve)
|
||||
)
|
||||
expect(useBoundStore.persist.hasHydrated()).toBe(true)
|
||||
|
||||
await useStore.persist.rehydrate()
|
||||
expect(useStore.persist.hasHydrated()).toBe(true)
|
||||
await useBoundStore.persist.rehydrate()
|
||||
expect(useBoundStore.persist.hasHydrated()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@ -46,7 +46,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
}
|
||||
|
||||
const onRehydrateStorageSpy = jest.fn()
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(
|
||||
() => ({
|
||||
count: 0,
|
||||
@ -60,7 +60,10 @@ describe('persist middleware with sync configuration', () => {
|
||||
)
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({ count: 42, name: 'test-storage' })
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 42,
|
||||
name: 'test-storage',
|
||||
})
|
||||
expect(onRehydrateStorageSpy).toBeCalledWith(
|
||||
{ count: 42, name: 'test-storage' },
|
||||
undefined
|
||||
@ -93,24 +96,24 @@ describe('persist middleware with sync configuration', () => {
|
||||
|
||||
const createStore = () => {
|
||||
const onRehydrateStorageSpy = jest.fn()
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
onRehydrateStorage: () => onRehydrateStorageSpy,
|
||||
})
|
||||
)
|
||||
return { useStore, onRehydrateStorageSpy }
|
||||
return { useBoundStore, onRehydrateStorageSpy }
|
||||
}
|
||||
|
||||
// Initialize from empty storage
|
||||
const { useStore, onRehydrateStorageSpy } = createStore()
|
||||
expect(useStore.getState()).toEqual({ count: 0 })
|
||||
const { useBoundStore, onRehydrateStorageSpy } = createStore()
|
||||
expect(useBoundStore.getState()).toEqual({ count: 0 })
|
||||
expect(onRehydrateStorageSpy).toBeCalledWith({ count: 0 }, undefined)
|
||||
|
||||
// Write something to the store
|
||||
useStore.setState({ count: 42 })
|
||||
expect(useStore.getState()).toEqual({ count: 42 })
|
||||
useBoundStore.setState({ count: 42 })
|
||||
expect(useBoundStore.getState()).toEqual({ count: 42 })
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage',
|
||||
JSON.stringify({ state: { count: 42 }, version: 0 })
|
||||
@ -119,10 +122,10 @@ describe('persist middleware with sync configuration', () => {
|
||||
// Create the same store a second time and check if the persisted state
|
||||
// is loaded correctly
|
||||
const {
|
||||
useStore: useStore2,
|
||||
useBoundStore: useBoundStore2,
|
||||
onRehydrateStorageSpy: onRehydrateStorageSpy2,
|
||||
} = createStore()
|
||||
expect(useStore2.getState()).toEqual({ count: 42 })
|
||||
expect(useBoundStore2.getState()).toEqual({ count: 42 })
|
||||
expect(onRehydrateStorageSpy2).toBeCalledWith({ count: 42 }, undefined)
|
||||
})
|
||||
|
||||
@ -141,7 +144,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -151,7 +154,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({ count: 99 })
|
||||
expect(useBoundStore.getState()).toEqual({ count: 99 })
|
||||
expect(migrateSpy).toBeCalledWith({ count: 42 }, 12)
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage',
|
||||
@ -176,7 +179,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -185,7 +188,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({ count: 0 })
|
||||
expect(useBoundStore.getState()).toEqual({ count: 0 })
|
||||
expect(console.error).toHaveBeenCalled()
|
||||
expect(onRehydrateStorageSpy).toBeCalledWith({ count: 0 }, undefined)
|
||||
})
|
||||
@ -203,7 +206,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
version: 13,
|
||||
@ -215,7 +218,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({ count: 0 })
|
||||
expect(useBoundStore.getState()).toEqual({ count: 0 })
|
||||
expect(onRehydrateStorageSpy).toBeCalledWith(
|
||||
undefined,
|
||||
new Error('migrate error')
|
||||
@ -237,7 +240,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
|
||||
const unstorableMethod = () => {}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0, unstorableMethod }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -247,7 +250,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
|
||||
const expectedState = { count: 1, unstorableMethod }
|
||||
|
||||
expect(useStore.getState()).toEqual(expectedState)
|
||||
expect(useBoundStore.getState()).toEqual(expectedState)
|
||||
expect(onRehydrateStorageSpy).toBeCalledWith(expectedState, undefined)
|
||||
})
|
||||
|
||||
@ -267,7 +270,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
|
||||
const unstorableMethod = () => {}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0, actions: { unstorableMethod } }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -283,7 +286,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
actions: {
|
||||
unstorableMethod,
|
||||
@ -303,7 +306,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -311,7 +314,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.getState()).toEqual({
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
})
|
||||
})
|
||||
@ -325,7 +328,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(
|
||||
() => ({
|
||||
object: {
|
||||
@ -359,7 +362,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
)
|
||||
)
|
||||
|
||||
useStore.setState({})
|
||||
useBoundStore.setState({})
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage',
|
||||
JSON.stringify({
|
||||
@ -388,14 +391,14 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
})
|
||||
)
|
||||
expect(useStore.persist.getOptions().name).toBeDefined()
|
||||
expect(useStore.persist.getOptions().name).toBe('test-storage')
|
||||
expect(useBoundStore.persist.getOptions().name).toBeDefined()
|
||||
expect(useBoundStore.persist.getOptions().name).toBe('test-storage')
|
||||
})
|
||||
|
||||
it('can change the options through the api', () => {
|
||||
@ -407,7 +410,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -415,20 +418,20 @@ describe('persist middleware with sync configuration', () => {
|
||||
})
|
||||
)
|
||||
|
||||
useStore.setState({})
|
||||
useBoundStore.setState({})
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage',
|
||||
'{"state":{"count":0},"version":0}'
|
||||
)
|
||||
|
||||
useStore.persist.setOptions({
|
||||
useBoundStore.persist.setOptions({
|
||||
name: 'test-storage-2',
|
||||
partialize: (state) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(state).filter(([key]) => key !== 'count')
|
||||
),
|
||||
})
|
||||
useStore.setState({})
|
||||
useBoundStore.setState({})
|
||||
expect(setItemSpy).toBeCalledWith(
|
||||
'test-storage-2',
|
||||
'{"state":{},"version":0}'
|
||||
@ -444,14 +447,14 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: removeItemSpy,
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
})
|
||||
)
|
||||
|
||||
useStore.persist.clearStorage()
|
||||
useBoundStore.persist.clearStorage()
|
||||
expect(removeItemSpy).toBeCalledWith('test-storage')
|
||||
})
|
||||
|
||||
@ -464,7 +467,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
@ -472,8 +475,8 @@ describe('persist middleware with sync configuration', () => {
|
||||
)
|
||||
|
||||
storage.getItem = () => storageValue
|
||||
useStore.persist.rehydrate()
|
||||
expect(useStore.getState()).toEqual({
|
||||
useBoundStore.persist.rehydrate()
|
||||
expect(useBoundStore.getState()).toEqual({
|
||||
count: 1,
|
||||
})
|
||||
})
|
||||
@ -485,17 +488,17 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
})
|
||||
)
|
||||
|
||||
expect(useStore.persist.hasHydrated()).toBe(true)
|
||||
expect(useBoundStore.persist.hasHydrated()).toBe(true)
|
||||
|
||||
await useStore.persist.rehydrate()
|
||||
expect(useStore.persist.hasHydrated()).toBe(true)
|
||||
await useBoundStore.persist.rehydrate()
|
||||
expect(useBoundStore.persist.hasHydrated()).toBe(true)
|
||||
})
|
||||
|
||||
it('can wait for rehydration through the api', async () => {
|
||||
@ -513,23 +516,23 @@ describe('persist middleware with sync configuration', () => {
|
||||
removeItem: () => {},
|
||||
}
|
||||
|
||||
const useStore = create(
|
||||
const useBoundStore = create(
|
||||
persist(() => ({ count: 0 }), {
|
||||
name: 'test-storage',
|
||||
getStorage: () => storage,
|
||||
})
|
||||
)
|
||||
|
||||
const hydrateUnsub1 = useStore.persist.onHydrate(onHydrateSpy1)
|
||||
useStore.persist.onHydrate(onHydrateSpy2)
|
||||
const hydrateUnsub1 = useBoundStore.persist.onHydrate(onHydrateSpy1)
|
||||
useBoundStore.persist.onHydrate(onHydrateSpy2)
|
||||
|
||||
const finishHydrationUnsub1 = useStore.persist.onFinishHydration(
|
||||
const finishHydrationUnsub1 = useBoundStore.persist.onFinishHydration(
|
||||
onFinishHydrationSpy1
|
||||
)
|
||||
useStore.persist.onFinishHydration(onFinishHydrationSpy2)
|
||||
useBoundStore.persist.onFinishHydration(onFinishHydrationSpy2)
|
||||
|
||||
storage.getItem = () => storageValue1
|
||||
await useStore.persist.rehydrate()
|
||||
await useBoundStore.persist.rehydrate()
|
||||
expect(onHydrateSpy1).toBeCalledWith({ count: 0 })
|
||||
expect(onHydrateSpy2).toBeCalledWith({ count: 0 })
|
||||
expect(onFinishHydrationSpy1).toBeCalledWith({ count: 1 })
|
||||
@ -539,7 +542,7 @@ describe('persist middleware with sync configuration', () => {
|
||||
finishHydrationUnsub1()
|
||||
|
||||
storage.getItem = () => storageValue2
|
||||
await useStore.persist.rehydrate()
|
||||
await useBoundStore.persist.rehydrate()
|
||||
expect(onHydrateSpy1).not.toBeCalledTimes(2)
|
||||
expect(onHydrateSpy2).toBeCalledWith({ count: 1 })
|
||||
expect(onFinishHydrationSpy1).not.toBeCalledTimes(2)
|
||||
|
||||
@ -57,23 +57,23 @@ describe('shallow', () => {
|
||||
})
|
||||
|
||||
describe('types', () => {
|
||||
it('works with useStore and array selector (#1107)', () => {
|
||||
const useStore = create(() => ({
|
||||
it('works with useBoundStore and array selector (#1107)', () => {
|
||||
const useBoundStore = create(() => ({
|
||||
villages: [] as { name: string }[],
|
||||
}))
|
||||
const Component = () => {
|
||||
const villages = useStore((state) => state.villages, shallow)
|
||||
const villages = useBoundStore((state) => state.villages, shallow)
|
||||
return <>{villages.length}</>
|
||||
}
|
||||
expect(Component).toBeDefined()
|
||||
})
|
||||
|
||||
it('works with useStore and string selector (#1107)', () => {
|
||||
const useStore = create(() => ({
|
||||
it('works with useBoundStore and string selector (#1107)', () => {
|
||||
const useBoundStore = create(() => ({
|
||||
refetchTimestamp: '',
|
||||
}))
|
||||
const Component = () => {
|
||||
const refetchTimestamp = useStore(
|
||||
const refetchTimestamp = useBoundStore(
|
||||
(state) => state.refetchTimestamp,
|
||||
shallow
|
||||
)
|
||||
|
||||
@ -46,7 +46,7 @@ it('can use exposed types', () => {
|
||||
storeApi.setState({ num: v })
|
||||
},
|
||||
}))
|
||||
const useStore = storeApi
|
||||
const useBoundStore = storeApi
|
||||
|
||||
const stateCreator: StateCreator<ExampleState> = (set, get) => ({
|
||||
num: 1,
|
||||
@ -74,7 +74,7 @@ it('can use exposed types', () => {
|
||||
_destroy: StoreApi<ExampleState>['destroy'],
|
||||
_equalityFn: (a: ExampleState, b: ExampleState) => boolean,
|
||||
_stateCreator: StateCreator<ExampleState>,
|
||||
_useStore: UseBoundStore<StoreApi<ExampleState>>
|
||||
_useBoundStore: UseBoundStore<StoreApi<ExampleState>>
|
||||
) {
|
||||
expect(true).toBeTruthy()
|
||||
}
|
||||
@ -91,7 +91,7 @@ it('can use exposed types', () => {
|
||||
storeApi.destroy,
|
||||
equalityFn,
|
||||
stateCreator,
|
||||
useStore
|
||||
useBoundStore
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user