Skip to content

feat(store): modularize global state into campaign/wallet/ui slices - #1

Open
Darkdruce wants to merge 1 commit into
mainfrom
feat/865-modularize-global-state-store
Open

feat(store): modularize global state into campaign/wallet/ui slices#1
Darkdruce wants to merge 1 commit into
mainfrom
feat/865-modularize-global-state-store

Conversation

@Darkdruce

Copy link
Copy Markdown
Owner

Summary

Splits the monolithic Zustand store into three independently-testable slices with scoped selector hooks, closing the source of unrelated re-renders and merge conflicts described in Fund-My-Cause#865.

Changes

New slice files

File Responsibility
store/campaignSlice.ts Transient campaign UI state: active campaign ID, optimistic contribution deltas, pledge modal flag, pledge amount draft
store/walletSlice.ts Re-exports useWalletStore + named typed selectors
store/uiSlice.ts Re-exports notification / modal / theme stores + named selectors per sub-domain
store/index.ts Barrel — single import point for all slices and selectors

Scoped selector hooks

Hook file Exported hooks
hooks/useCampaignSlice.ts useCampaignSlice(), usePledgeModal(), useOptimisticDelta(id)
hooks/useWalletSlice.ts useWalletSlice(), useWalletStatus(), useWalletSigning()
hooks/useUiSlice.ts useUiSlice(), useNotifSlice(), useModalSlice(), useThemeSlice()

All hooks use useShallow to prevent re-renders when unsubscribed fields change.

Consumer migrations (no behaviour change)

  • hooks/useWallet.tsuseWalletSlice()
  • hooks/useModal.tsuseModalSlice()
  • hooks/useNotifications.tsuseNotifSlice()
  • components/ModalRendereruseModalSlice()
  • components/WalletSelectModalHostuseWalletSlice()

Backward compatibility

  • All existing action names preserved (connectWith, disconnect, signTx, openModal, etc.)
  • Direct store imports (useWalletStore, useModalStore, etc.) continue to work — nothing removed

Tests

  • 67 new tests across three test files (campaignSlice.test.ts, walletSlice.test.ts, uiSlice.test.ts)
  • Covers all reducers, actions, and selectors in isolation
  • Existing useWallet.test.tsx (11 tests) remains green
  • ESLint and Prettier hooks pass at commit time

What was tested

  • npx tsc --noEmit — 0 errors in new files
  • npx jest store/__tests__ — 67/67 pass
  • npx jest hooks/useWallet.test — 11/11 pass

Closes Fund-My-Cause#865

…und-My-Cause#865)

Split the monolithic store into three independently-testable Zustand
slices with scoped selector hooks and named selectors.

Slice layout
------------
store/campaignSlice.ts   – transient campaign UI state: active campaign ID,
                           optimistic contribution deltas, pledge modal open
                           flag, pledge amount draft
store/walletSlice.ts     – re-exports useWalletStore + named selectors
store/uiSlice.ts         – re-exports notification/modal/theme stores + named
                           selectors for each sub-domain
store/index.ts           – barrel; single import point for all slices

Scoped selector hooks
---------------------
hooks/useCampaignSlice.ts  useCampaignSlice() / usePledgeModal() /
                           useOptimisticDelta(contractId)
hooks/useWalletSlice.ts    useWalletSlice() / useWalletStatus() /
                           useWalletSigning()
hooks/useUiSlice.ts        useUiSlice() / useNotifSlice() /
                           useModalSlice() / useThemeSlice()

Consumer migrations
-------------------
- hooks/useWallet.ts         → useWalletSlice()
- hooks/useModal.ts          → useModalSlice()
- hooks/useNotifications.ts  → useNotifSlice()
- components/ModalRenderer   → useModalSlice()
- components/WalletSelectModalHost → useWalletSlice()

Store interface exports
-----------------------
WalletStoreState, NotificationStoreState, ModalStoreState, ThemeStoreState
are now exported so the slice barrel and tests can reference them without
circular imports.

Unit tests (67 passing)
-----------------------
store/__tests__/campaignSlice.test.ts  – all reducer, action & selector paths
store/__tests__/walletSlice.test.ts    – all selector paths + derived selectors
store/__tests__/uiSlice.test.ts        – notification, modal, theme stores +
                                         all named selectors

Existing tests: useWallet.test.tsx (11 tests) remain green.

Closes Fund-My-Cause#865
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Frontend] Modularize global state store

1 participant