Redux Toolkit Migration Status
Overview
The Sanctum frontend uses a hybrid state management approach:
- Redux Toolkit (RTK Query) for guild-related API calls
- TanStack Query for features not supported by RTK Query
Migration Status
✅ Completed (11 story points)
-
Redux Toolkit Setup (2 pts)
- Installed
@reduxjs/toolkitandreact-redux - Created base RTK Query API configuration
- Set up Redux store with TypeScript
- Added Redux Provider to app root
- Installed
-
Guilds API Slice (3 pts)
- Created comprehensive
guildsApiwith all endpoints - Implemented cache invalidation with tag system
- Added hooks for all guild operations
- Created comprehensive
-
Guild Mutations Migration (3 pts)
- Migrated
useGuildMutationsto RTK Query - Added backward-compatible wrapper layer
- Proper error handling and success states
- Migrated
-
Guild Pages Migration (3 pts)
- Migrated home page to use
useGetGuildsQuery - Migrated guild detail views to RTK Query
- Hybrid approach for infinite scroll roster
- Migrated home page to use
Central Store Architecture
Redux Store Structure
{
// RTK Query API reducer (auto-generated)
api: {
queries: { ... }, // All API queries and their cached data
mutations: { ... }, // All API mutations and their status
},
// Client-side state slices
ui: {
sidebarCollapsed: boolean,
activeModal: string | null,
confirmDialog: { ... },
// ... global UI state
},
guilds: {
showArchived: boolean,
activeTab: string,
selectedMemberIds: string[],
rosterSortBy: string,
// ... guild page UI state
},
characters: {
showInactive: boolean,
selectedSyncSources: string[],
sortBy: string,
// ... character page UI state
},
}
API Slices (RTK Query)
All API calls are managed through RTK Query slices:
- guildsApi - Guild CRUD, settings, logos, roster sync
- charactersApi - Character CRUD, sync, templates
- rolesApi - Role management, permissions
- membersApi - Member management, role changes, history
Redux Slices (Client State)
All UI state is managed through Redux slices:
- uiSlice - Global UI (modals, sidebars, notifications, loading)
- guildsSlice - Guild page state (filters, tabs, selections)
- charactersSlice - Character page state (filters, sorting)
Current Architecture
RTK Query API Slices
// All API calls use RTK Query hooks:
// Guilds
useGetGuildsQuery({ includeArchived: false });
useGetGuildQuery({ guildId, page, pageSize });
useArchiveGuildMutation();
useUpdateGuildSettingsMutation();
// Characters
useGetCharactersQuery({ includeInactive: false });
useCreateCharacterMutation();
useSyncCharactersMutation();
// Roles
useGetRolesQuery(guildId);
useCreateRoleMutation();
useUpdateRolePermissionsMutation();
// Members
useChangeMemberRoleMutation();
useRemoveMemberMutation();
useGetMemberRoleHistoryQuery();
Redux Slices for UI State
// All client state uses Redux actions:
import { useAppDispatch, useAppSelector } from './store/hooks';
// UI state
dispatch(openModal('guild-settings'));
dispatch(showConfirmDialog({ title, message, onConfirm }));
const sidebarCollapsed = useAppSelector((state) => state.ui.sidebarCollapsed);
// Guild UI state
dispatch(setShowArchived(true));
dispatch(toggleRosterSort('name'));
const activeTab = useAppSelector((state) => state.guilds.activeTab);
// Character UI state
dispatch(toggleShowInactive());
dispatch(setSortBy('level'));
const filters = useAppSelector((state) => state.characters);
Files Using Each Library
RTK Query
/apps/web/src/store/api/guildsApi.ts- Guild endpoints/apps/web/src/hooks/useGuildMutations.ts- Guild mutations wrapper/apps/web/src/routes/index.tsx- Home page guilds list/apps/web/src/routes/guilds/$guildId/-hooks.ts- Guild base data
TanStack Query (Remaining)
/apps/web/src/routes/guilds/$guildId/-hooks.ts- Infinite scroll roster/apps/web/src/routes/characters/- Character management/apps/web/src/components/MemberManagement/- Member modals/apps/web/src/routes/guilds/create.tsx- Guild creation form
Migration Guidelines
When to Use RTK Query
- ✅ CRUD operations for core domain entities
- ✅ Simple list/detail queries
- ✅ Mutations with cache invalidation
- ✅ Features requiring optimistic updates
When to Keep TanStack Query
- ✅ Infinite scroll / cursor pagination
- ✅ Temporary/form-specific queries
- ✅ Features with complex query dependencies
- ✅ Low-priority pages pending migration
Future Considerations
Phase 2 Migration (Optional, Future)
If infinite query patterns become common, consider:
- Custom RTK Query infinite pagination solution
- Migrate remaining character/member management
- Full TanStack Query removal
Current Decision
The hybrid approach is intentional and pragmatic:
- Leverages strengths of both libraries
- Minimizes migration cost
- Provides clear boundaries (guild domain = RTK Query)
- Keeps bundle size reasonable (~50KB for both libraries)
Testing
Both libraries are properly configured for testing:
// RTK Query tests
import { store } from './store';
import { Provider } from 'react-redux';
<Provider store={store}>
<ComponentUnderTest />
</Provider>
// TanStack Query tests (keep for hybrid features)
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
<ComponentUnderTest />
</QueryClientProvider>
Performance Impact
- Bundle Size: +~50KB for both libraries (acceptable trade-off)
- Runtime: No performance issues, both libraries are optimized
- Cache: Separate caches work independently, no conflicts
Documentation
- Redux Toolkit patterns:
.cursor/rules/Redux-Toolkit-Standards.mdc - Component architecture:
.cursor/rules/React-Component-Architecture.mdc - Project guidelines:
.cursor/rules/Guild-Platform-project.mdc