store-data-structures
LobeHub Zustand store data-shape patterns. Use when designing store state, list/detail splits, normalized maps, reducers, messagesMap, topicsMap, or choosing shared type sources.
Security Assessment
About store-data-structures
store-data-structures is a code-convention reference documenting how LobeHub structures data inside Zustand stores. It addresses a common frontend state-management problem: choosing the right data shape for fast list rendering, caching multiple detail pages, and supporting ergonomic optimistic updates. The guidance is opinionated and pattern-focused rather than executable — a set of DO/DON'T rules with TypeScript examples.
The core patterns separate list state from detail state: simple arrays for lists (refreshed as a whole, no per-item mutation) and normalized maps (Record<string, Detail>) for details, which allow caching multiple detail pages, per-item loading states, and multi-page navigation without refetching. Types come from @lobechat/types (never @lobechat/database), with distinct Detail and List item types where the List type is a subset that excludes heavy fields rather than an extends of Detail. The skill shows an initialState slice pattern with list, detail-map, per-item loading, and mutation-state flags, and a reducer pattern using Immer's produce with a discriminated-union of set/update/delete actions plus internal_dispatch* slice methods that keep dispatch shapes out of the component layer and skip no-op sets to avoid re-renders.
It targets LobeHub contributors and, more broadly, React/Zustand developers designing store state for list/detail splits, normalized maps (messagesMap, topicsMap), reducers, and shared type sources. The skill is marked user-invocable: false, meaning it is intended as internal reference guidance consulted during development rather than a user-triggered command.
FAQ
When should I use a Map versus an Array?
Use a Map (Record<string, Detail>) with a reducer for detail data that needs multi-page caching, optimistic updates, and per-item loading states; use a simple array for list display that refreshes as a whole without per-item mutation.
Where should store types come from?
From @lobechat/types — never from @lobechat/database. Each entity gets a Detail type and a List item type, where the List type is a subset excluding heavy fields (not an extends of Detail, which would pull heavy fields back in).
Why use a reducer for the detail map?
A reducer built on Immer's produce gives immutable updates, a type-safe discriminated union of actions, testability as a pure function, and reuse across optimistic updates and server-data writes; internal_dispatch* methods keep dispatch shapes out of UI components.
Is this skill something a user invokes directly?
No. It is marked user-invocable: false and serves as internal code-convention reference guidance consulted while designing LobeHub store slices.
How are unnecessary re-renders avoided?
The internal_dispatch method compares the next map against the current one and skips the set call entirely when nothing changed.
Install store-data-structures
Quick Setup:
- Copy the skill folder to
.claude/skills/ - Claude will automatically detect and use the skill
Repository
lobehub/lobehub