@kurokeita/add-skill 2.6.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -64
- package/dist/bin/cli.js +270 -478
- package/dist/skills/statusline-setup/.claude-plugin/plugin.json +1 -1
- package/dist/skills/statusline-setup/SKILL.md +21 -436
- package/dist/skills/statusline-setup/mod/hooks/register.tsx +93 -103
- package/dist/skills/statusline-setup/mod/tests/work.test.ts +28 -10
- package/dist/skills/statusline-setup/mod/types/index.d.ts +2 -1
- package/dist/skills/universalize-agents/reference/mapping.md +3 -2
- package/package.json +3 -3
- package/dist/agents/backend-specialist.md +0 -277
- package/dist/agents/code-archaeologist.md +0 -114
- package/dist/agents/database-architect.md +0 -238
- package/dist/agents/debugger.md +0 -231
- package/dist/agents/devops-engineer.md +0 -242
- package/dist/agents/documentation-writer.md +0 -104
- package/dist/agents/explorer-agent.md +0 -79
- package/dist/agents/frontend-specialist.md +0 -594
- package/dist/agents/game-developer.md +0 -162
- package/dist/agents/mobile-developer.md +0 -383
- package/dist/agents/orchestrator.md +0 -435
- package/dist/agents/penetration-tester.md +0 -188
- package/dist/agents/performance-optimizer.md +0 -191
- package/dist/agents/product-manager.md +0 -122
- package/dist/agents/product-owner.md +0 -106
- package/dist/agents/project-planner.md +0 -408
- package/dist/agents/qa-automation-engineer.md +0 -109
- package/dist/agents/security-auditor.md +0 -171
- package/dist/agents/test-engineer.md +0 -158
- package/dist/skills/agent-identifier/SKILL.md +0 -431
- package/dist/skills/agent-identifier/examples/agent-creation-prompt.md +0 -247
- package/dist/skills/agent-identifier/examples/complete-agent-examples.md +0 -432
- package/dist/skills/agent-identifier/references/agent-creation-system-prompt.md +0 -215
- package/dist/skills/agent-identifier/references/system-prompt-design.md +0 -419
- package/dist/skills/agent-identifier/references/triggering-examples.md +0 -508
- package/dist/skills/agent-identifier/scripts/validate-agent.sh +0 -217
- package/dist/skills/code-review-excellence/SKILL.md +0 -525
- package/dist/skills/component-refactoring/SKILL.md +0 -492
- package/dist/skills/component-refactoring/references/complexity-patterns.md +0 -493
- package/dist/skills/component-refactoring/references/component-splitting.md +0 -477
- package/dist/skills/component-refactoring/references/hook-extraction.md +0 -317
- package/dist/skills/context7-guidelines/SKILL.md +0 -31
- package/dist/skills/feature-design-assistant/SKILL.md +0 -371
- package/dist/skills/find-bugs/SKILL.md +0 -75
- package/dist/skills/frontend-design/SKILL.md +0 -45
- package/dist/skills/go-concurrency-patterns/SKILL.md +0 -657
- package/dist/skills/grill-me/SKILL.md +0 -9
- package/dist/skills/handoff/SKILL.md +0 -16
- package/dist/skills/koreader-plugin-development/SKILL.md +0 -141
- package/dist/skills/koreader-plugin-development/examples/2-example-patch.lua +0 -17
- package/dist/skills/koreader-plugin-development/examples/_meta.lua +0 -6
- package/dist/skills/koreader-plugin-development/examples/helloworld.lua +0 -36
- package/dist/skills/koreader-plugin-development/references/debugging.md +0 -92
- package/dist/skills/koreader-plugin-development/references/events-and-widgets.md +0 -102
- package/dist/skills/koreader-plugin-development/references/patches.md +0 -118
- package/dist/skills/koreader-plugin-development/references/plugin-anatomy.md +0 -97
- package/dist/skills/make-instruction/SKILL.md +0 -68
- package/dist/skills/make-prompt/SKILL.md +0 -70
- package/dist/skills/make-skill/SKILL.md +0 -147
- package/dist/skills/prd-to-tasks/SKILL.md +0 -164
- package/dist/skills/react-native-async-patterns/SKILL.md +0 -256
- package/dist/skills/react-native-performance/SKILL.md +0 -425
- package/dist/skills/react-native-testing/SKILL.md +0 -458
- package/dist/skills/react-native-zustand-patterns/SKILL.md +0 -343
- package/dist/skills/skill-creator/SKILL.md +0 -385
- package/dist/skills/skill-creator/scripts/init_skill.cjs +0 -235
- package/dist/skills/skill-creator/scripts/package_skill.cjs +0 -84
- package/dist/skills/skill-creator/scripts/validate_skill.cjs +0 -127
- package/dist/skills/skill-development/SKILL.md +0 -676
- package/dist/skills/skill-development/references/skill-creator-original.md +0 -210
- package/dist/skills/sql-optimization-patterns/SKILL.md +0 -509
- package/dist/skills/test-driven-development/SKILL.md +0 -114
- package/dist/skills/test-driven-development/deep-modules.md +0 -33
- package/dist/skills/test-driven-development/interface-design.md +0 -35
- package/dist/skills/test-driven-development/mocking.md +0 -68
- package/dist/skills/test-driven-development/refactoring.md +0 -10
- package/dist/skills/test-driven-development/tests.md +0 -61
- package/dist/skills/vercel-react-best-practices/AGENTS.md +0 -2410
- package/dist/skills/vercel-react-best-practices/SKILL.md +0 -127
- package/dist/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/dist/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -49
- package/dist/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
- package/dist/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
- package/dist/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -36
- package/dist/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
- package/dist/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/dist/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
- package/dist/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
- package/dist/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/dist/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/dist/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
- package/dist/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
- package/dist/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
- package/dist/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
- package/dist/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
- package/dist/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -82
- package/dist/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
- package/dist/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
- package/dist/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
- package/dist/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
- package/dist/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
- package/dist/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/dist/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
- package/dist/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -50
- package/dist/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
- package/dist/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/dist/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/dist/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
- package/dist/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/dist/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/dist/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/dist/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/dist/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/dist/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/dist/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/dist/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
- package/dist/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
- package/dist/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/dist/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/dist/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
- package/dist/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
- package/dist/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/dist/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
- package/dist/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
- package/dist/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
- package/dist/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
- package/dist/skills/web-design-guidelines/SKILL.md +0 -40
- package/dist/skills/workflow-patterns/SKILL.md +0 -623
- package/dist/skills/write-prd/SKILL.md +0 -162
- package/dist/workflows/brainstorm.md +0 -113
- package/dist/workflows/create.md +0 -60
- package/dist/workflows/debug.md +0 -107
- package/dist/workflows/deploy.md +0 -178
- package/dist/workflows/enhance.md +0 -64
- package/dist/workflows/github-pull-request-create.md +0 -134
- package/dist/workflows/orchestrate.md +0 -246
- package/dist/workflows/plan.md +0 -90
- package/dist/workflows/preview.md +0 -83
- package/dist/workflows/status.md +0 -87
- package/dist/workflows/test.md +0 -144
- package/dist/workflows/ui-ux-pro-max.md +0 -315
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: react-native-zustand-patterns
|
|
3
|
-
description: Zustand state management patterns for React Native. Use when working with Zustand stores, debugging state timing issues, or implementing async actions in Zustand.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Zustand Patterns for React Native
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
Zustand's simplicity hides important timing details. `set()` is synchronous, but React re-renders are batched. `getState()` escapes stale closures. Async actions in stores need careful handling. Understanding these internals prevents subtle bugs.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## Pattern: set() is Synchronous, Renders are Batched
|
|
15
|
-
|
|
16
|
-
**Problem:** Assuming state is "ready" for React immediately after `set()`.
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
const useStore = create((set, get) => ({
|
|
20
|
-
count: 0,
|
|
21
|
-
|
|
22
|
-
increment: () => {
|
|
23
|
-
set({ count: get().count + 1 });
|
|
24
|
-
// State IS updated here (set is sync)
|
|
25
|
-
console.log(get().count); // ✅ Shows new value
|
|
26
|
-
|
|
27
|
-
// But React hasn't re-rendered yet
|
|
28
|
-
// Component will see old value until next render cycle
|
|
29
|
-
},
|
|
30
|
-
}));
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
**Key insight:**
|
|
34
|
-
|
|
35
|
-
- `set()` updates the store synchronously
|
|
36
|
-
- `getState()` immediately reflects the new value
|
|
37
|
-
- React components re-render asynchronously (batched)
|
|
38
|
-
|
|
39
|
-
**When this matters:**
|
|
40
|
-
|
|
41
|
-
- Chaining multiple state updates
|
|
42
|
-
- Validating state after update
|
|
43
|
-
- Debugging "stale" component values
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Pattern: getState() Escapes Stale Closures
|
|
48
|
-
|
|
49
|
-
**Problem:** Callbacks and async functions capture state at creation time. Using `get()` or `getState()` always gets current state.
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
const useStore = create((set, get) => ({
|
|
53
|
-
answers: {},
|
|
54
|
-
|
|
55
|
-
// WRONG - state captured at function creation
|
|
56
|
-
saveAnswerBad: (questionId: string, value: number) => {
|
|
57
|
-
setTimeout(() => {
|
|
58
|
-
const answers = get().answers; // ❌ This is fine
|
|
59
|
-
// But if someone passed `answers` as a parameter...
|
|
60
|
-
}, 1000);
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
// CORRECT - always use get() for current state
|
|
64
|
-
saveAnswer: async (questionId: string, value: number) => {
|
|
65
|
-
await someAsyncOperation();
|
|
66
|
-
// After await, use get() to ensure current state
|
|
67
|
-
const currentAnswers = get().answers;
|
|
68
|
-
set({ answers: { ...currentAnswers, [questionId]: value } });
|
|
69
|
-
},
|
|
70
|
-
}));
|
|
71
|
-
|
|
72
|
-
// In components - same principle
|
|
73
|
-
function Component() {
|
|
74
|
-
const answers = useStore((s) => s.answers);
|
|
75
|
-
|
|
76
|
-
const handleSave = async () => {
|
|
77
|
-
await delay(1000);
|
|
78
|
-
// answers here is stale! Captured at render time
|
|
79
|
-
|
|
80
|
-
// Use getState() for current value
|
|
81
|
-
const current = useStore.getState().answers;
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
**Rule:** After any `await`, use `get()` or `getState()` - never rely on closure-captured values.
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## Pattern: Async Actions in Stores
|
|
91
|
-
|
|
92
|
-
**Problem:** Async actions need explicit `async/await` and careful state reads after awaits.
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
const useStore = create((set, get) => ({
|
|
96
|
-
loading: false,
|
|
97
|
-
data: null,
|
|
98
|
-
error: null,
|
|
99
|
-
|
|
100
|
-
// WRONG - no async keyword, race condition prone
|
|
101
|
-
fetchDataBad: (id: string) => {
|
|
102
|
-
set({ loading: true });
|
|
103
|
-
api.fetch(id).then((data) => {
|
|
104
|
-
set({ data, loading: false });
|
|
105
|
-
});
|
|
106
|
-
// Returns immediately, caller can't await
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
// CORRECT - proper async action
|
|
110
|
-
fetchData: async (id: string) => {
|
|
111
|
-
set({ loading: true, error: null });
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const data = await api.fetch(id);
|
|
115
|
-
// Re-read state after await if needed
|
|
116
|
-
if (get().loading) { // Check we're still in loading state
|
|
117
|
-
set({ data, loading: false });
|
|
118
|
-
}
|
|
119
|
-
} catch (error) {
|
|
120
|
-
set({ error: error.message, loading: false });
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
}));
|
|
124
|
-
|
|
125
|
-
// Caller can properly await
|
|
126
|
-
await useStore.getState().fetchData('123');
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Pattern: Selector Stability
|
|
132
|
-
|
|
133
|
-
**Problem:** Selectors that create new objects cause unnecessary re-renders.
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
// WRONG - creates new object every render
|
|
137
|
-
const data = useStore((state) => ({
|
|
138
|
-
name: state.name,
|
|
139
|
-
count: state.count,
|
|
140
|
-
}));
|
|
141
|
-
|
|
142
|
-
// CORRECT - use multiple selectors
|
|
143
|
-
const name = useStore((state) => state.name);
|
|
144
|
-
const count = useStore((state) => state.count);
|
|
145
|
-
|
|
146
|
-
// OR - use shallow comparison (Zustand 4.x)
|
|
147
|
-
import { shallow } from 'zustand/shallow';
|
|
148
|
-
|
|
149
|
-
const { name, count } = useStore(
|
|
150
|
-
(state) => ({ name: state.name, count: state.count }),
|
|
151
|
-
shallow
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// Zustand 5.x - use useShallow hook
|
|
155
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
156
|
-
|
|
157
|
-
const { name, count } = useStore(
|
|
158
|
-
useShallow((state) => ({ name: state.name, count: state.count }))
|
|
159
|
-
);
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Pattern: Derived State
|
|
165
|
-
|
|
166
|
-
**Problem:** Computing derived values in selectors vs storing them.
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
const useStore = create((set, get) => ({
|
|
170
|
-
answers: {},
|
|
171
|
-
|
|
172
|
-
// WRONG - storing derived state that can become stale
|
|
173
|
-
totalAnswers: 0,
|
|
174
|
-
updateTotalAnswers: () => {
|
|
175
|
-
set({ totalAnswers: Object.keys(get().answers).length });
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
// CORRECT - compute in selector (always fresh)
|
|
179
|
-
// answers: {}, // Just store the source data
|
|
180
|
-
}));
|
|
181
|
-
|
|
182
|
-
// Selector computes derived value
|
|
183
|
-
const totalAnswers = useStore((state) => Object.keys(state.answers).length);
|
|
184
|
-
|
|
185
|
-
// For expensive computations, memoize outside the store
|
|
186
|
-
import { useMemo } from 'react';
|
|
187
|
-
|
|
188
|
-
function Component() {
|
|
189
|
-
const answers = useStore((state) => state.answers);
|
|
190
|
-
const expensiveResult = useMemo(() => {
|
|
191
|
-
return computeExpensiveAnalysis(answers);
|
|
192
|
-
}, [answers]);
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Pattern: Store Subscriptions for Side Effects
|
|
199
|
-
|
|
200
|
-
**Problem:** Need to react to state changes outside React components.
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
// Subscribe to specific state changes
|
|
204
|
-
const unsubscribe = useStore.subscribe(
|
|
205
|
-
(state) => state.answers,
|
|
206
|
-
(answers, prevAnswers) => {
|
|
207
|
-
console.log('Answers changed:', { prev: prevAnswers, current: answers });
|
|
208
|
-
// Persist to storage, send analytics, etc.
|
|
209
|
-
},
|
|
210
|
-
{ equalityFn: shallow }
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
// In Zustand 4.x with subscribeWithSelector middleware
|
|
214
|
-
import { subscribeWithSelector } from 'zustand/middleware';
|
|
215
|
-
|
|
216
|
-
const useStore = create(
|
|
217
|
-
subscribeWithSelector((set, get) => ({
|
|
218
|
-
answers: {},
|
|
219
|
-
// ...
|
|
220
|
-
}))
|
|
221
|
-
);
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## Pattern: Testing Zustand Stores
|
|
227
|
-
|
|
228
|
-
**Problem:** Tests need to reset store state and verify async flows.
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
// Store with reset capability
|
|
232
|
-
const initialState = {
|
|
233
|
-
answers: {},
|
|
234
|
-
loading: false,
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const useStore = create((set, get) => ({
|
|
238
|
-
...initialState,
|
|
239
|
-
|
|
240
|
-
// Actions...
|
|
241
|
-
|
|
242
|
-
// Reset for testing
|
|
243
|
-
_reset: () => set(initialState),
|
|
244
|
-
}));
|
|
245
|
-
|
|
246
|
-
// Test
|
|
247
|
-
describe('Assessment Store', () => {
|
|
248
|
-
beforeEach(() => {
|
|
249
|
-
useStore.getState()._reset();
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('saves answers during retake flow', async () => {
|
|
253
|
-
const store = useStore.getState();
|
|
254
|
-
|
|
255
|
-
// Full async flow
|
|
256
|
-
await store.loadCompletedAnswers(assessmentId);
|
|
257
|
-
await store.enableSkillAreaRetake('fundamentals');
|
|
258
|
-
|
|
259
|
-
// Verify state after async
|
|
260
|
-
expect(store.getState().retakeAreas).toContain('fundamentals');
|
|
261
|
-
|
|
262
|
-
// Continue flow
|
|
263
|
-
await store.saveAnswer('q1', 4);
|
|
264
|
-
|
|
265
|
-
// Verify final state
|
|
266
|
-
expect(useStore.getState().userAnswers['q1']).toBe(4);
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
## Pattern: Debugging State Changes
|
|
274
|
-
|
|
275
|
-
**Problem:** Tracking down when/where state changed unexpectedly.
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
// Add logging middleware
|
|
279
|
-
import { devtools } from 'zustand/middleware';
|
|
280
|
-
|
|
281
|
-
const useStore = create(
|
|
282
|
-
devtools(
|
|
283
|
-
(set, get) => ({
|
|
284
|
-
// ... your store
|
|
285
|
-
}),
|
|
286
|
-
{ name: 'AssessmentStore' }
|
|
287
|
-
)
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
// Manual logging for specific debugging
|
|
291
|
-
const useStore = create((set, get) => ({
|
|
292
|
-
answers: {},
|
|
293
|
-
|
|
294
|
-
saveAnswer: (questionId: string, value: number) => {
|
|
295
|
-
console.log('[saveAnswer] Before:', {
|
|
296
|
-
questionId,
|
|
297
|
-
value,
|
|
298
|
-
currentAnswers: get().answers,
|
|
299
|
-
retakeAreas: get().retakeAreas,
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
set((state) => ({
|
|
303
|
-
answers: { ...state.answers, [questionId]: value },
|
|
304
|
-
}));
|
|
305
|
-
|
|
306
|
-
console.log('[saveAnswer] After:', {
|
|
307
|
-
answers: get().answers,
|
|
308
|
-
});
|
|
309
|
-
},
|
|
310
|
-
}));
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
---
|
|
314
|
-
|
|
315
|
-
## Common Pitfalls
|
|
316
|
-
|
|
317
|
-
| Pitfall | Solution |
|
|
318
|
-
| --------- | ---------- |
|
|
319
|
-
| Stale closure after await | Use `get()` after every await |
|
|
320
|
-
| Selector returns new object | Use `shallow` or multiple selectors |
|
|
321
|
-
| Action not awaitable | Add `async` keyword, return promise |
|
|
322
|
-
| State seems stale in component | Component hasn't re-rendered yet - use `getState()` for immediate reads |
|
|
323
|
-
| Can't find when state changed | Add devtools middleware or manual logging |
|
|
324
|
-
|
|
325
|
-
---
|
|
326
|
-
|
|
327
|
-
## Zustand 5.x Migration Notes
|
|
328
|
-
|
|
329
|
-
If upgrading from 4.x:
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
// 4.x - shallow from main package
|
|
333
|
-
import { shallow } from 'zustand/shallow';
|
|
334
|
-
|
|
335
|
-
// 5.x - useShallow hook for React
|
|
336
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
337
|
-
|
|
338
|
-
// 4.x - type parameter often needed
|
|
339
|
-
const useStore = create<StoreType>()((set, get) => ({...}));
|
|
340
|
-
|
|
341
|
-
// 5.x - improved type inference
|
|
342
|
-
const useStore = create((set, get) => ({...}));
|
|
343
|
-
```
|