Sync Behavior with Zustand
This document outlines how switching from useReducer/useState to Zustand would impact the event generation and synchronization flow.
1. Decoupling from the Render Cycle
STATUS: MITIGATED in current implementation. The
Studiocomponent currently uses the Ref Pattern to stabilize callbacks, ensuringReact.memoworks correctly for sibling nodes.
Current (Optimized useReducer):
- The
Studiocomponent re-renders on state changes. - However, child components (
MindMapNodeComponent) are passed stable callback references (viauseRef/useCallback). - Sibling nodes DO NOT re-render on keystrokes because their props (
nodedata and handler functions) remain reference-equal. - Performance is O(1) regarding the number of nodes (only the edited node renders).
With Zustand:
- The store exists outside of React.
- We can subscribe to state changes independently of React components.
- Benefit: While performance is similar to the optimized
useReducerapproach (both avoid sibling renders), Zustand allows us to move logic entirely out of the React Component tree, resulting in cleaner files (Separation of Concerns).
2. Middleware for Side Effects
Current:
- Data persistence logic is mixed into the
Studiocomponent or custom hooks (useAutoSave).
With Zustand:
- We can implement a custom Sync Middleware.
- This middleware can intercept actions (like
UPDATE_TEXT) and handle the queueing logic directly. - Impact: Cleaner architecture. The UI components (
Studio.tsx) generate events, but the "Wiring" to the database happens invisibly in the store layer.
3. Transient Updates
Current:
- Typing updates the React state -> triggers Virtual DOM diffing -> updates DOM.
- This is generally fast enough (~60fps) for text inputs unless the tree is massive.
With Zustand:
- Enables Transient Updates (updating the store without triggering any React re-renders for listeners that haven't opted in).
- Impact: For extremely high-frequency events (like 120hz mouse drag coordinates), using transient updates can bypass React entirely for smoother animation, though React's own performance is usually sufficient for text.
4. Does it fix the "Every Keystroke" Event?
Not automatically.
- If we subscribe to the store and write to DB on every change, we still generate an event for every keystroke.
- However, Zustand makes it easier to implement Debouncing or Throttling in the middleware or subscription layer:typescript
// Easier to debounce in a store subscription than in a useEffect const save = debounce((nodes) => db.saveNodes(nodes), 500) useStore.subscribe((state) => save(state.nodes))
Summary Comparison
| Feature | Current (Optimized useReducer) | Zustand |
|---|---|---|
| Event Generation | Coupled to React Render Cycle | Decoupled (Store Subscription) |
| Performance | Good: Sibling re-renders prevented via Ref Pattern | Excellent: Selective re-renders / Transient updates |
| Code Structure | Logic mixed inside Component (Studio.tsx) | Logic separated in Store / Middleware |
| Refactoring Cost | N/A (Already built) | High (Rewrite state layer) |
Conclusion: The move to Zustand would be primarily for Architectural Cleanliness (moving logic out of UI components) rather than a raw performance necessity, as the current implementation already solves the main re-render bottleneck.