Apollo vs Redux State
This page helps you decide where state belongs: Apollo cache + generated GraphQL hooks for server-state, and Redux Toolkit slices for client/UI flow state.How it works
I like to think in terms of “what owns the source of truth”:1) Server-state: generated hooks + Apollo cache
When you call ause*Query / use*Mutation hook from apps/portal/src/gql/hooks.ts, Apollo manages loading/error/data and caches results in InMemoryCache.
2) Client-state: Redux Toolkit slices
Redux is used for “what the user is doing right now”:- selected product / quantity during checkout
- wizard steps
- local UI toggles that don’t need to be shared across tabs
apps/portal/src/redux/store.ts
For example:
apps/portal/src/redux/slices/checkoutSlice.ts
Extending this system
Use this recipe when you add client/UI flow state and wire it into Redux.- Decide if the state is server-state or client-state.
- if it comes from the API, it belongs in Apollo cache (via generated hooks)
- if it drives UI flow, it belongs in Redux
- Add a slice (or extend
checkoutSlice) inapps/portal/src/redux/slices/.
apps/portal/src/redux/slices/checkoutSlice.ts already contains checkout UI state like product, quantity, and billingAddress.
-
Register the slice reducer in
apps/portal/src/redux/store.ts. - Use Redux selectors/actions from the components that need them.
- Verify:
What not to do
These anti-patterns lead to duplicated “state sources” and brittle UI behavior. ❌ Never duplicate server-state into Redux when Apollo cache can serve it. ❌ Never use Redux as a “second cache” for GraphQL responses. ❌ Never move API-derived entitlements, scopes, or billing rules into Redux; those are server-side rules and UI should follow the GraphQL contract.File conventions
This section keeps Redux wiring and slice locations consistent. Prefer:- Keep slice state normalized and explicit.
- Use generated hook data as read-only inputs to your UI logic.
