English | 简体ä¸ć–‡
Some utils for zustand
A replacement createContext from zustand/context that is deprecated in v4 and will be removed in v5. (Discussion: #1276)
import create from 'zustand'
import { createContext } from 'zustand-utils'
const { Provider, useStore } = createContext()
const createStore = () => create(...)
const App = () => (
<Provider createStore={createStore}>
...
</Provider>
)
const Component = () => {
const state = useStore()
const slice = useStore(selector)
...
a wrapper for zustand devtools middleware that with config to enable devtools.(Discussion: #1266)
import { optionalDevtools } from 'zustand-utils';
type Store = {
foo: string;
};
export const createStore = (withDevtools?: boolean) => {
// can enable or controlled by config
const devtools = optionalDevtools(withDevtools);
// use as zustands/middleware devtools
return create<Store>()(devtools((set) => ({})));
};
What's improve?
zustands/middleware
's devtools
have an option enable
, but it doesn't work if set to false in development.
Migration from zustand-v3-create-context.md
import create from "zustand";
import { createContext } from 'zustand-utils';
// Best practice: You can move the below createContext() and createStore to a separate file(store.js) and import the Provider, useStore here/wherever you need.
const { Provider, useStore } = createContext();
const createStore = () =>
create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 })
}));
const Button = () => {
return (
{/** store() - This will create a store for each time using the Button component instead of using one store for all components **/}
<Provider createStore={createStore}>
<ButtonChild />
</Provider>
);
};
const ButtonChild = () => {
const state = useStore();
return (
<div>
{state.bears}
<button
onClick={() => {
state.increasePopulation();
}}
>
+
</button>
</div>
);
};
export default function App() {
return (
<div className="App">
<Button />
<Button />
</div>
);
}
Migration from zustand-v3-create-context.md
import create from 'zustand';
import { createContext } from 'zustand-utils';
const { Provider, useStore } = createContext();
export default function App({ initialBears }) {
return (
<Provider
createStore={() =>
create((set) => ({
bears: initialBears,
increase: () => set((state) => ({ bears: state.bears + 1 })),
}))
}
>
<Button />
</Provider>
);
}
a most usage of createContext is refactoring an app to a component. Here's progress:
- Create an App without context :
// store.ts
import create from 'zustand';
export const useStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}));
components in app use useStore
to consume store:
// Component.ts
import { useStore } from './store';
const ButtonChild = () => {
const state = useStore();
return (
<div>
{state.bears}
<button
onClick={() => {
state.increasePopulation();
}}
>
+
</button>
</div>
);
};
export default ButtonChild;
- Just wrapper the App with
createContext
, and don't need to refactor any code in children components.
// store.ts
import create from "zustand";
+ const createStore = ()=> create((set) => ({
- export const useStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 })
}));
+ const { Provider, useStore } = createContext();
+ export { Provider, useStore , createStore }
// Wrapper.tsx
import { createStore, Provider } from './store';
const Wrapper = () => {
return (
<Provider createStore={createStore}>
<ButtonChild />
</Provider>
);
};
It become a component, can be used in any other app.
createStoreUpdater
is a function for updating the value of a specified key in the Store.
createStoreUpdater
takes a StoreApi
object as its parameter, which contains methods for manipulating the Store, such as getState
, setState
, subscribe
, and destroy
.
createStoreUpdater
returns a function that takes the following parameters:
key
: the key in the Store that needs to be updated;value
: the value that needs to be updated;deps
: an array of dependencies, defaults to[value]
;setStoreState
: an optional callback function for updating the Store state, defaults tostoreApi.setState
.
createStoreUpdater
returns a function that updates the value of the specified key in the Store.
import { createStoreUpdater } from 'path/to/createStoreUpdater';
import { useStore } from 'path/to/useStore';
interface User {
name: string;
age: number;
}
const storeApi = useStore<User>({ name: '', age: 0 });
const updateUser = createStoreUpdater(storeApi);
// Update name
updateUser('name', 'John Doe');
// Update age
updateUser('age', 18);
In the example above, we first create a Store using useStore
, then create an updater updateUser
using createStoreUpdater
, and finally update the name
and age
in the Store by calling updateUser
.