State Management
The Pizza Chef Frontend uses Redux Toolkit for predictable, centralized state management. This document details the implementation, including store configuration, slices, actions, and selectors.Store Configuration
The Redux store is configured insrc/store/index.ts:
Type-Safe Hooks
The store exports custom typed hooks that provide full TypeScript support:useAppDispatch: Typed version ofuseDispatchwith correct action typesuseAppSelector: Typed version ofuseSelectorwith RootState inference
State Shape
The complete state tree structure:Pizza Slice
Manages the pizza catalog and filtering state.Initial State
The pizza slice loads data from two sources:- Static catalog:
pizzas.jsonfile with default menu - Custom pizzas: User-created pizzas from localStorage
Actions
setSearch(search: string)
Updates the search query and persists to localStorage.
setCategory(category: string)
Filters pizzas by category (Vegetarian, Meat, Seafood, Spicy, or ‘all’).
setMaxPrice(price: number)
Sets the maximum price filter.
setSortBy(sortOption: SortOption)
Changes the sort order for the pizza list.
'name-asc'- Alphabetical A-Z'name-desc'- Alphabetical Z-A'price-asc'- Price low to high'price-desc'- Price high to low
addPizzaToCatalog(pizza: Pizza)
Adds a custom pizza to the catalog and persists it to localStorage.
Exported Actions
Order Slice
Manages the shopping cart (current order) and order history.Initial State
The order slice rehydrates from localStorage:Discount Calculation
The order slice includes automatic discount calculation for bulk orders:- 3+ pizzas of the same type → 10% discount on that line item
- Discounts are calculated per pizza type, not across the entire order
- Real-time updates in cart and detail views
Actions
setLoading(loading: boolean)
Controls the loading state for async operations.
addToOrder({ pizza: Pizza, quantity: number })
Adds a pizza to the cart or updates quantity if already present.
- Automatically merges quantities for the same pizza
- Recalculates discounts when quantity changes
- Persists cart to localStorage immediately
removeFromOrder(pizzaId: string)
Removes a pizza completely from the cart.
updateQuantity({ pizzaId: string, quantity: number })
Updates the quantity of a specific pizza in the cart.
- Recalculates line totals and discounts
- Persists changes immediately
- Safe operation (no-op if item not found)
clearOrder()
Empties the current cart without saving to order history.
addOrderToHistory(order: Order)
Completes an order by moving it to history and clearing the cart.
- Adds order to history
- Clears current cart
- Updates both localStorage keys
Exported Actions
Selectors
While the application primarily uses direct state access viauseAppSelector, you can create memoized selectors for complex computations:
Best Practices
1. Always Use Typed Hooks
2. Destructure Actions from Slice
3. Keep Reducers Pure
Redux Toolkit uses Immer, so you can write “mutating” logic safely:4. Persist Critical State Only
Only persist state that needs to survive page refreshes:- ✅ Current cart, order history, custom pizzas, user preferences
- ❌ Loading states, temporary UI state, error messages
5. Handle localStorage Errors
Always wrap localStorage operations in try-catch blocks:Performance Considerations
Redux Toolkit Optimizations
- Immer: Efficient structural sharing prevents unnecessary object creation
- DevTools: Disabled in production builds automatically
- Memoization: Selectors cache results until inputs change
Avoiding Re-renders
Use selective subscriptions to prevent unnecessary component updates:Testing Redux Slices
Example test for the order slice:Next Steps
- Routing - Learn about route configuration
- Data Persistence - localStorage implementation details