Skip to main content

Overview

TMT uses Redux Toolkit for state management with Redux Persist for automatic state persistence to local storage. The store is configured with custom middleware to handle serialization and persistence actions.

Store Configuration

The Redux store is configured using configureStore from Redux Toolkit with persistence support.

Basic Setup

Store.js:84-92
export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }),
});
export const persistor = persistStore(store);

Redux Persist Configuration

Redux Persist automatically saves and rehydrates the Redux state to/from local storage.

Persist Configuration

Store.js:45-49
const persistConfig = {
  key: 'root',
  storage,
  whitelist: ['auth', 'customizer', 'setup']
};
key
string
required
The key used to store the persisted state in storage
storage
Storage
required
The storage engine to use (defaults to localStorage)
whitelist
string[]
Array of reducer keys to persist. Only auth, customizer, and setup states are persisted across sessions

Persisted Reducer

Store.js:82
const persistedReducer = persistReducer(persistConfig, rootReducer);
The root reducer is wrapped with persistReducer to enable automatic persistence.

Middleware Configuration

The store uses custom middleware configuration to handle non-serializable values in Redux Persist actions.

Serialization Check

The middleware ignores Redux Persist action types to prevent serialization warnings:
  • FLUSH - Flush pending state to storage
  • REHYDRATE - Rehydrate persisted state
  • PAUSE - Pause persistence
  • PERSIST - Trigger persistence
  • PURGE - Clear persisted state
  • REGISTER - Register reducers
Store.js:86-91
middleware: (getDefaultMiddleware) =>
  getDefaultMiddleware({
    serializableCheck: {
      ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
    },
  }),

Root Reducer

The root reducer combines all slice reducers into a single reducer tree.
Store.js:51-80
const rootReducer = combineReducers({
  customizer: CustomizerReducer,
  setup: SetupReducer,
  staff: StaffReducer,
  collaborators: CollaboratorsReducer,
  clients: ClientsReducer,
  customers: CustomerReducer,
  contracts: ContractReducer,
  addendums: AddendumReducer,
  tickets: TicketReducer,
  queryTickets: QueryTicketReducer,
  auth: authReducer,
  eventVenues: EventsVenuesReduces,
  events: EventsReduces,
  credentials: CredentialsReduces,
  Transactions: TransactionsReducer,
  offices: OfficesReducer,
  officeEvents: OfficeEventReducer,
  officeTransactions: OfficeTransactionReducer,
  paymentsMethod: PaymentsMethodsReducer,
  payouts: PayoutsReducer,
  custodyAccounts: CustodyAccountsReducer,
  orders: OrdersReducer,
  officeCollaborators: ActiveOfficeCollaboratorsReducer,
  contractsLegal: ContractsLegalReducer,
  ordersPayout: OrdersPayoutReducer,
  portals: PortalsReducer,
  documents: DocumentsReducer,
  marketing: MarketingReducer,
});

State Tree Structure

customizer
object
UI customization settings (persisted)
setup
object
Application setup configuration (persisted)
auth
object
Authentication state and user information (persisted)
staff
object
Staff users management state
collaborators
object
Collaborators management state
clients
object
Client users management state
customers
object
Customer users management state
contracts
object
Contracts management state
addendums
object
Contract addendums management state
tickets
object
Event tickets management state
queryTickets
object
Ticket query and search state
eventVenues
object
Event venues management state
events
object
Events management state
credentials
object
User credentials management state
Transactions
object
Transactions management state
offices
object
Box offices management state
officeEvents
object
Active office events state
officeTransactions
object
Office-specific transactions state
paymentsMethod
object
Payment methods configuration state
payouts
object
Payout methods management state
custodyAccounts
object
Custody accounts management state
orders
object
Orders management state
officeCollaborators
object
Office collaborators management state
Legal contracts management state
ordersPayout
object
Order payouts management state
portals
object
Customer portals management state
documents
object
Documents management state
marketing
object
Marketing campaigns management state

Usage

Importing the Store

import store from './store/Store';
import { Provider } from 'react-redux';

function App() {
  return (
    <Provider store={store}>
      {/* Your app components */}
    </Provider>
  );
}

Accessing State

import { useSelector } from 'react-redux';

function MyComponent() {
  const user = useSelector((state) => state.auth.user);
  const events = useSelector((state) => state.events.Events);
  
  return (
    <div>
      <p>Welcome, {user?.name}</p>
      <p>Total Events: {events.length}</p>
    </div>
  );
}

Dispatching Actions

import { useDispatch } from 'react-redux';
import { fetchStaffUsers } from './store/apps/Users/StaffSlice';

function StaffList() {
  const dispatch = useDispatch();
  
  useEffect(() => {
    dispatch(fetchStaffUsers());
  }, [dispatch]);
  
  // Component implementation
}

Best Practices

Keep Actions Serializable

Avoid storing non-serializable values (functions, promises, etc.) in Redux state. Use middleware or side effects for async operations.

Use Selectors

Create reusable selectors to access state values and avoid duplicating logic across components.

Minimal Persistence

Only persist essential state (auth, settings) to avoid storage bloat. Most data should be fetched on demand.

Type Safety

Consider using TypeScript with Redux Toolkit for better type safety and autocomplete support.

Build docs developers (and LLMs) love