How to Create and Update Store
Best practices for creating and updating store
Store with Actions (Recommended)
We recommend encapsulating the state modification logic within your store for cleaner, more maintainable code. This keeps your components focused on presentation while centralizing business logic.
const counterStore = createStore({
count: 0,
increment() {
// Use the store instance to mutate the state directly
counterStore.setState((state) => {
state.count++;
});
},
// Async actions are also supported
async incrementAsync() {
await new Promise((resolve) => setTimeout(resolve, 1000));
// Access current state with `store.value`
const currentCount = counterStore.value.count;
// Call other store actions
counterStore.value.increment();
},
});
// Clean API calls
counterStore.value.increment();
await counterStore.value.incrementAsync();
State Update Patterns
Let's explore different approaches using a realistic user store:
const userStore = createStore({
name: "John",
followers: 0,
settings: {
language: "en",
theme: {
primary: "blue",
},
},
updateSettings(newSettings) {
userStore.setState((state) => {
state.settings = newSettings;
});
},
});
1. Immer-style Updates (Recommended)
Best for partial updates and stores with actions. Immer handles immutability automatically.
// Natural and readable
userStore.setState((state) => {
state.followers++;
state.settings.theme.primary = "red";
});
So you don't need to use store.value
to read state and spread it like this:
userStore.setState({
...userStore.value,
followers: userStore.value.followers + 1,
settings: {
...userStore.value.settings,
theme: {
...userStore.value.settings.theme,
primary: "red",
},
},
});
2. Direct Object Updates
Ideal for simple stores without actions or complete state replacements.
const counterStore = createStore({ count: 0 });
counterStore.setState({
count: counterStore.value.count + 1,
});
But it's more troublesome for complex state updates, you need to manually spread the original state.
For example, update a store with actions:
userStore.setState({
...userStore.value, // spread the entire state with original actions
followers: userStore.value.followers + 1, // update the followers
});
3. Partial State Merging
Luckily, ZenBox allows you to update partial state like this:
userStore.setState({
name: "Jane",
followers: userStore.value.followers + 1,
age: 18, // new properties are ignored, existing structure preserved
});
What a life saver!
Notes:
- Only first-level merging is supported
- For nested updates, use the Immer approach
4. Direct Value Assignment
You can also use store.value = x
to update state directly.
// Complete replacement
userStore.value = {
name: "Jane",
followers: 100,
settings: {
language: "zh",
theme: {
primary: "red",
},
},
};
// Partial replacement (same as setState)
userStore.value = {
name: "Jane",
followers: userStore.value.followers + 1,
};
Notes:
- Can be confusing for partial updates
- Prefer Immer-style for complex changes