This project demonstrates a micro-frontend architecture using React Native with Redux Toolkit for state management.
The project uses a hierarchical Redux store setup with the following structure:
The core store serves as the main state management solution for the application. It provides:
- Global user state management
- Theme and UI preferences
- Core API integration
- Shared utilities for micro apps
// Core store structure
{
user: {
user: User | null;
loading: boolean;
error: string | null;
},
mobile: {
theme: 'light' | 'dark';
isOnline: boolean;
}
}
Each micro app has its own Redux store that can work both independently and as part of the main app.
// Support store structure
{
tickets: {
items: Ticket[];
loading: boolean;
error: string | null;
}
}
// Payments store structure
{
transactions: {
transactions: Transaction[];
loading: boolean;
error: string | null;
},
paymentMethods: {
methods: PaymentMethod[];
loading: boolean;
error: string | null;
},
settings: {
settings: PaymentSettings;
loading: boolean;
error: string | null;
}
}
The stores are integrated using a hierarchical provider setup:
// Main App
<StoreProvider>
<App />
</StoreProvider>
// Support App
<CombinedStoreProvider> // Combines core and support stores
<SupportApp />
</CombinedStoreProvider>
// Payments App
<CombinedStoreProvider> // Combines core and payments stores
<PaymentsApp />
</CombinedStoreProvider>
// Using hooks from @micro/core-store
const { user } = useMainAppUser();
const theme = useAppSelector((state) => state.mobile.theme);
// Using hooks from feature packages
const tickets = useAppSelector((state) => state.tickets.items);
const transactions = useAppSelector((state) => state.transactions.transactions);
Each store includes RTK Query APIs for data fetching:
// Core API
const { data: currentUser } = useGetCurrentUserQuery();
// Support API
const { data: tickets } = useGetTicketsQuery();
const [createTicket] = useCreateTicketMutation();
// Payments API
const { data: transactions } = useGetTransactionsQuery();
const [addTransaction] = useAddTransactionMutation();
- RTK Query automatically updates the store on API calls
- Changes are reflected across all components using the data
- Optimistic updates for better UX
- Centralized error handling in slices
- Error states propagated to components
- Automatic error clearing on successful operations
- Automatic loading states from RTK Query
- Manual loading state management in slices
- Loading indicators in components
All state changes are logged with descriptive emojis:
- π€ User-related actions
- π« Ticket-related actions
- π³ Payment-related actions
- β³ Loading states
- β Errors
import { useMainAppUser, useAppSelector } from '@micro/core-store';
const MyComponent = () => {
const { user } = useMainAppUser();
const theme = useAppSelector((state) => state.mobile.theme);
return <View>{/* Component JSX */}</View>;
};
import {
useAppSelector,
useCreateTicketMutation,
} from '@micro/features-support';
const SupportComponent = () => {
const tickets = useAppSelector((state) => state.tickets.items);
const [createTicket] = useCreateTicketMutation();
return <View>{/* Component JSX */}</View>;
};
import {
useAppSelector,
useAddTransactionMutation,
} from '@micro/features-payments';
const PaymentsComponent = () => {
const transactions = useAppSelector(
(state) => state.transactions.transactions
);
const [addTransaction] = useAddTransactionMutation();
return <View>{/* Component JSX */}</View>;
};
-
State Access
- Use typed selectors for type safety
- Access only needed state portions
- Use memoized selectors for performance
-
State Updates
- Use RTK Query for API operations
- Dispatch actions through proper slices
- Handle optimistic updates when needed
-
Error Handling
- Always handle error states
- Show user-friendly error messages
- Clear errors when appropriate
-
Loading States
- Show loading indicators during operations
- Handle loading states gracefully
- Prevent duplicate operations
-
Adding New State
- Create a new slice in appropriate package
- Add proper TypeScript types
- Include error and loading states
- Add debug logging
-
API Integration
- Use RTK Query for API calls
- Define proper tag types for caching
- Handle success and error cases
- Update local state appropriately
-
Testing
- Test selectors and reducers
- Mock API calls in tests
- Test error and loading states
- Verify state updates