docs: update map and set guide (#3258)

* Enhance Maps and Sets usage documentation in Zustand

Expanded the documentation on using Maps and Sets in Zustand, including guidelines for reading and updating these data structures. Added examples for creating new instances and explained the importance of reference changes for state updates.

* feat: update format
This commit is contained in:
Danilo Britto 2025-10-12 07:59:26 -05:00 committed by GitHub
parent 20ad3f8891
commit 95850110ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -3,25 +3,113 @@ title: Map and Set Usage
nav: 10
---
You need to wrap Maps and Sets inside an object. When you want its update to be reflected (e.g. in React),
you do it by calling `setState` on it:
# Map and Set in Zustand
**You can view a codesandbox here: https://codesandbox.io/s/late-https-bxz9qy**
Map and Set are mutable data structures. To use them in Zustand, you must create new instances when updating.
```js
import { create } from 'zustand'
## Map
const useFooBar = create(() => ({ foo: new Map(), bar: new Set() }))
### Reading a Map
function doSomething() {
// doing something...
```typescript
const foo = useSomeStore((state) => state.foo)
```
// If you want to update some React component that uses `useFooBar`, you have to call setState
// to let React know that an update happened.
// Following React's best practices, you should create a new Map/Set when updating them:
useFooBar.setState((prev) => ({
foo: new Map(prev.foo).set('newKey', 'newValue'),
bar: new Set(prev.bar).add('newKey'),
}))
### Updating a Map
Always create a new Map instance:
```ts
// Update single entry
set((state) => ({
foo: new Map(state.foo).set(key, value),
}))
// Delete entry
set((state) => {
const next = new Map(state.foo)
next.delete(key)
return { foo: next }
})
// Update multiple entries
set((state) => {
const next = new Map(state.foo)
next.set('key1', 'value1')
next.set('key2', 'value2')
return { foo: next }
})
// Clear
set({ foo: new Map() })
```
## Set
### Reading a Set
```ts
const bar = useSomeStore((state) => state.bar)
```
### Updating a Set
Always create a new Set instance:
```ts
// Add item
set((state) => ({
bar: new Set(state.bar).add(item),
}))
// Delete item
set((state) => {
const next = new Set(state.bar)
next.delete(item)
return { bar: next }
})
// Toggle item
set((state) => {
const next = new Set(state.bar)
next.has(item) ? next.delete(item) : next.add(item)
return { bar: next }
})
// Clear
set({ bar: new Set() })
```
## Why New Instances?
Zustand detects changes by comparing references. Mutating a Map or Set doesn't change its reference:
```ts
// ❌ Wrong - same reference, no re-render
set((state) => {
state.foo.set(key, value)
return { foo: state.foo }
})
// ✅ Correct - new reference, triggers re-render
set((state) => ({
foo: new Map(state.foo).set(key, value),
}))
```
## Pitfall: Type Hints for Empty Collections
Provide type hints when initializing empty Maps and Sets:
```ts
{
ids: new Set([] as string[]),
users: new Map([] as [string, User][])
}
```
Without type hints, TypeScript infers `never[]` which prevents adding items later.
## CodeSandbox Demo
Basic: https://stackblitz.com/edit/vitejs-vite-5cu5ddvx