{"id":4447,"date":"2025-08-09T14:04:54","date_gmt":"2025-08-09T14:04:54","guid":{"rendered":"https:\/\/uplatz.com\/blog\/?p=4447"},"modified":"2025-08-09T14:05:09","modified_gmt":"2025-08-09T14:05:09","slug":"redux-pocket-book","status":"publish","type":"post","link":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/","title":{"rendered":"Redux Pocket Book"},"content":{"rendered":"<p><!-- Redux Pocket Book \u2014 Uplatz (50 Cards, Wide Layout, Readable Code, Scoped Styles) --><\/p>\n<div style=\"margin:16px 0;\">\n<style>\n    .wp-redux-pb { font-family: Arial, sans-serif; max-width: 1320px; margin:0 auto; }\n    .wp-redux-pb .heading{\n      background: linear-gradient(135deg, #eef2ff, #f5f3ff); \/* light indigo -> light violet *\/\n      color:#0f172a; padding:22px 24px; border-radius:14px;\n      text-align:center; margin-bottom:18px; box-shadow:0 8px 20px rgba(0,0,0,.08);\n      border:1px solid #cbd5e1;\n    }\n    .wp-redux-pb .heading h2{ margin:0; font-size:2.1rem; letter-spacing:.2px; }\n    .wp-redux-pb .heading p{ margin:6px 0 0; font-size:1.02rem; opacity:.9; }<\/p>\n<p>    \/* Wide, dense grid *\/\n    .wp-redux-pb .grid{\n      display:grid; gap:14px;\n      grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));\n    }\n    @media (min-width:1200px){\n      .wp-redux-pb .grid{ grid-template-columns: repeat(3, 1fr); }\n    }<\/p>\n<p>    .wp-redux-pb .section-title{\n      grid-column:1\/-1; background:#f8fafc; border-left:8px solid #7c3aed; \/* violet *\/\n      padding:12px 16px; border-radius:10px; font-weight:700; color:#0f172a; font-size:1.08rem;\n      box-shadow:0 2px 8px rgba(0,0,0,.05); border:1px solid #e2e8f0;\n    }\n    .wp-redux-pb .card{\n      background:#ffffff; border-left:6px solid #7c3aed;\n      padding:18px; border-radius:12px;\n      box-shadow:0 6px 14px rgba(0,0,0,.06);\n      transition:transform .12s ease, box-shadow .12s ease;\n      border:1px solid #e5e7eb;\n    }\n    .wp-redux-pb .card:hover{ transform: translateY(-3px); box-shadow:0 10px 22px rgba(0,0,0,.08); }\n    .wp-redux-pb .card h3{ margin:0 0 10px; font-size:1.12rem; color:#0f172a; }\n    .wp-redux-pb .card p{ margin:0; font-size:.96rem; color:#334155; line-height:1.62; }<\/p>\n<p>    \/* Color helpers *\/\n    .bg-blue { border-left-color:#3b82f6 !important; background:#eef6ff !important; }\n    .bg-green{ border-left-color:#10b981 !important; background:#f0fdf4 !important; }\n    .bg-amber{ border-left-color:#f59e0b !important; background:#fffbeb !important; }\n    .bg-violet{ border-left-color:#7c3aed !important; background:#f5f3ff !important; }\n    .bg-rose{ border-left-color:#ef4444 !important; background:#fff1f2 !important; }\n    .bg-cyan{ border-left-color:#06b6d4 !important; background:#ecfeff !important; }\n    .bg-lime{ border-left-color:#22c55e !important; background:#ecfdf5 !important; }\n    .bg-orange{ border-left-color:#f97316 !important; background:#fff7ed !important; }\n    .bg-indigo{ border-left-color:#6366f1 !important; background:#eef2ff !important; }\n    .bg-emerald{ border-left-color:#059669 !important; background:#ecfdf5 !important; }\n    .bg-slate{ border-left-color:#334155 !important; background:#f8fafc !important; }<\/p>\n<p>    \/* Utilities & code *\/\n    .tight ul{ margin:0; padding-left:18px; }\n    .tight li{ margin:4px 0; }\n    .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }\n    .wp-redux-pb code{ background:#f1f5f9; padding:0 4px; border-radius:4px; border:1px solid #e2e8f0; }\n    .wp-redux-pb pre{\n      background:#f5f5f5; color:#111827; border:1px solid #e5e7eb;\n      padding:12px; border-radius:8px; overflow:auto; font-size:.92rem; line-height:1.55;\n    }\n    .q{font-weight:700;}\n    .qa p{ margin:8px 0; }\n  <\/style>\n<div class=\"wp-redux-pb\">\n<div class=\"heading\">\n<h2>Redux Pocket Book \u2014 Uplatz<\/h2>\n<p>50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20+ Interview Q&amp;A included<\/p>\n<\/p><\/div>\n<div class=\"grid\">\n      <!-- ===================== SECTION 1: FOUNDATIONS (1\u201310) ===================== --><\/p>\n<div class=\"section-title\">Section 1 \u2014 Foundations<\/div>\n<div class=\"card bg-violet\">\n<h3>1) What is Redux?<\/h3>\n<p>Redux is a predictable state container for JavaScript apps. It centralizes state in a single store, updates state via dispatched actions, and uses pure reducer functions to compute the next state. With Redux Toolkit (RTK), modern Redux is concise and batteries-included.<\/p>\n<pre><code class=\"mono\">npm i @reduxjs\/toolkit react-redux<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>2) Three Core Principles<\/h3>\n<p>Single source of truth (one store), state is read-only (update via actions), and changes are made with pure reducers. This yields predictable updates and debuggable flows.<\/p>\n<pre><code class=\"mono\">\/\/ Action\r\n{ type: 'cart\/addItem', payload: { id:'p1' } }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-green\">\n<h3>3) Redux Toolkit (RTK)<\/h3>\n<p>RTK simplifies setup with <code>configureStore<\/code>, <code>createSlice<\/code>, Immer-powered immutable updates, and good defaults (DevTools, thunk). Prefer RTK over \u201chand-rolled\u201d Redux.<\/p>\n<pre><code class=\"mono\">import { configureStore, createSlice } from '@reduxjs\/toolkit'\r\nconst cartSlice = createSlice({\r\n  name:'cart', initialState:{ items:[] },\r\n  reducers:{ addItem:(s,a)=>{ s.items.push(a.payload) } }\r\n})\r\nexport const { addItem } = cartSlice.actions\r\nexport const store = configureStore({ reducer:{ cart: cartSlice.reducer }})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>4) The Data Flow<\/h3>\n<p>UI dispatches an action \u2192 store runs reducers \u2192 new state computed \u2192 subscribed components re-render via selectors.<\/p>\n<pre><code class=\"mono\">dispatch(addItem({ id:'p1' }))<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>5) React Binding (react-redux)<\/h3>\n<p>Wrap app in <code>&lt;Provider store={store}&gt;<\/code>. Components use <code>useSelector<\/code> to read state and <code>useDispatch<\/code> to dispatch.<\/p>\n<pre><code class=\"mono\">import { Provider, useSelector, useDispatch } from 'react-redux'<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>6) Reducers Must Be Pure<\/h3>\n<p>No side effects, no async, no mutations. With RTK, you \u201cmutate\u201d but Immer produces immutable copies safely.<\/p>\n<pre><code class=\"mono\">toggle:(s)=>{ s.open = !s.open } \/\/ safe via Immer<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>7) Store Shape &#038; Slices<\/h3>\n<p>Split state by domain into slices. RTK merges reducers under keys in <code>configureStore<\/code>. Keep state normalized and serializable.<\/p>\n<pre><code class=\"mono\">const store = configureStore({ reducer:{ auth:authReducer, cart:cartReducer }})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>8) Actions &#038; Action Creators<\/h3>\n<p><code>createSlice<\/code> generates action creators and types for you. Keep payloads minimal and well-defined.<\/p>\n<pre><code class=\"mono\">dispatch(cartSlice.actions.removeItem('p1'))<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>9) Selectors<\/h3>\n<p>Selectors read state slices. Use memoized selectors (Reselect) for derived data to prevent unnecessary re-renders.<\/p>\n<pre><code class=\"mono\">const total = useSelector(s =&gt; s.cart.items.length)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>10) Q&amp;A \u2014 \u201cWhy Redux in 2025?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> For complex apps needing predictable global state, time-travel debugging, middleware, devtools, and ecosystem support. RTK + RTK Query reduce boilerplate dramatically.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 2: REDUX TOOLKIT DEEP DIVE (11\u201320) ===================== --><\/p>\n<div class=\"section-title\">Section 2 \u2014 Redux Toolkit Deep Dive<\/div>\n<div class=\"card bg-violet\">\n<h3>11) createSlice<\/h3>\n<p>Defines initial state, reducer case reducers, and generates actions. Immer allows mutable-looking code that is actually immutable.<\/p>\n<pre><code class=\"mono\">const todos = createSlice({\r\n  name:'todos', initialState:[],\r\n  reducers:{\r\n    add:(s,a)=>{ s.push({ id:Date.now(), title:a.payload, done:false }) },\r\n    toggle:(s,a)=>{ const t=s.find(x=>x.id===a.payload); if(t) t.done=!t.done }\r\n  }\r\n})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>12) configureStore<\/h3>\n<p>Creates the store with good defaults: DevTools, thunk, and serializable\/immutable checks (can be customized\/disabled in prod).<\/p>\n<pre><code class=\"mono\">const store = configureStore({ reducer:{ todos: todos.reducer } })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-green\">\n<h3>13) createAction &#038; createReducer<\/h3>\n<p>Lower-level helpers for custom patterns. Most apps can use <code>createSlice<\/code> exclusively.<\/p>\n<pre><code class=\"mono\">const increment = createAction('counter\/increment')<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>14) prepare Callbacks<\/h3>\n<p>Use <code>prepare<\/code> to format payloads (e.g., add IDs, timestamps) before reducer runs.<\/p>\n<pre><code class=\"mono\">add: {\r\n  reducer:(s,a)=>{ s.push(a.payload) },\r\n  prepare:(title)=>({ payload:{ id:nanoid(), title, createdAt:Date.now() } })\r\n}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>15) Extra Reducers<\/h3>\n<p>Respond to actions defined elsewhere (e.g., RTK Query or thunks) using <code>extraReducers<\/code>.<\/p>\n<pre><code class=\"mono\">extraReducers:(b)=>{ b.addCase(logout, (s)=>[]) }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>16) Middleware Overview<\/h3>\n<p>Middleware intercept actions for async, logging, analytics, or side effects. RTK includes thunk by default; you can add custom middleware in <code>middleware:<\/code> option.<\/p>\n<pre><code class=\"mono\">const mw = store =&gt; next =&gt; action =&gt; { \/* ... *\/ return next(action) }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>17) DevTools &#038; Tracing<\/h3>\n<p>Redux DevTools enable time travel, action replay, and state diffs. Keep actions serializable; avoid class instances and Dates (serialize). Toggle checks in prod to reduce overhead.<\/p>\n<pre><code class=\"mono\">const store = configureStore({ reducer, devTools:true })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>18) Normalized State<\/h3>\n<p>Store entities by ID (maps + arrays of IDs) using <code>createEntityAdapter<\/code> for CRUD helpers and selectors.<\/p>\n<pre><code class=\"mono\">const usersAdapter = createEntityAdapter()\r\nconst usersSlice = createSlice({ name:'users', initialState:usersAdapter.getInitialState(), reducers:{\r\n  upsertMany: usersAdapter.upsertMany\r\n}})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>19) Serializability Rules<\/h3>\n<p>State\/actions should be serializable for DevTools, persistence, and debugging. Use dates as ISO strings, plain objects\/arrays. If needed, configure serializableCheck exceptions.<\/p>\n<pre><code class=\"mono\">configureStore({ reducer, middleware:(gDM)=&gt;gDM({ serializableCheck:false }) })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>20) Q&amp;A \u2014 \u201cWhy normalized state?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Avoids duplication, simplifies updates, and yields O(1) entity access. It also plays nicely with memoized selectors and cache invalidation.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 3: ASYNC, RTK QUERY & SIDE EFFECTS (21\u201330) ===================== --><\/p>\n<div class=\"section-title\">Section 3 \u2014 Async Logic, RTK Query &#038; Side Effects<\/div>\n<div class=\"card bg-violet\">\n<h3>21) Thunks (createAsyncThunk)<\/h3>\n<p>Standard way to handle async. Generates pending\/fulfilled\/rejected action types; handle them in extraReducers. Attach <code>rejectWithValue<\/code> for typed errors.<\/p>\n<pre><code class=\"mono\">export const fetchUsers = createAsyncThunk('users\/fetch', async(_, { rejectWithValue })=>{\r\n  try{ const r = await fetch('\/api\/users').then(r=&gt;r.json()); return r }\r\n  catch(e){ return rejectWithValue(e.message) }\r\n})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>22) Handling Async States<\/h3>\n<p>Keep <code>status<\/code> (idle\/loading\/succeeded\/failed) and <code>error<\/code>. Reduce UI branching and enable consistent spinners &#038; toasts.<\/p>\n<pre><code class=\"mono\">extraReducers:(b)=>{\r\n  b.addCase(fetchUsers.pending, (s)=>{ s.status='loading' })\r\n   .addCase(fetchUsers.fulfilled, (s,a)=>{ s.status='succeeded'; s.list=a.payload })\r\n   .addCase(fetchUsers.rejected, (s,a)=>{ s.status='failed'; s.error=a.payload })\r\n}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-green\">\n<h3>23) RTK Query Overview<\/h3>\n<p>RTK Query is a data fetching+cache library built on Redux. It auto-generates hooks, handles caching, invalidation, polling, and streaming.<\/p>\n<pre><code class=\"mono\">import { createApi, fetchBaseQuery } from '@reduxjs\/toolkit\/query\/react'\r\nexport const api = createApi({\r\n  reducerPath:'api', baseQuery:fetchBaseQuery({ baseUrl:'\/api' }),\r\n  endpoints:(b)=>({ getUsers:b.query({ query:()=&gt;'users' }) })\r\n})\r\nexport const { useGetUsersQuery } = api<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>24) RTK Query Setup<\/h3>\n<p>Add the API reducer and middleware to the store. Use generated hooks in components.<\/p>\n<pre><code class=\"mono\">const store = configureStore({\r\n  reducer:{ [api.reducerPath]: api.reducer, other: otherReducer },\r\n  middleware:(gDM)=&gt; gDM().concat(api.middleware)\r\n})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>25) Caching &#038; Invalidation<\/h3>\n<p>Tag-based invalidation lets mutations refresh specific queries. Keep cache logic declarative.<\/p>\n<pre><code class=\"mono\">endpoints:(b)=>({\r\n  getUser:b.query({ query:(id)=&gt;`users\/${id}`, providesTags:(r,id)=&gt;[{type:'User',id}] }),\r\n  updateUser:b.mutation({ query:(u)=&gt;({ url:`users\/${u.id}`, method:'PUT', body:u }),\r\n    invalidatesTags:(r,e,arg)=&gt;[{type:'User', id:arg.id}] })\r\n})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>26) Polling &#038; Streaming<\/h3>\n<p>RTKQ supports <code>pollingInterval<\/code> in hooks and <code>onCacheEntryAdded<\/code> for websockets\/streams.<\/p>\n<pre><code class=\"mono\">const { data } = useGetUsersQuery(undefined, { pollingInterval: 30000 })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>27) Optimistic Updates<\/h3>\n<p>Use <code>updateQueryData<\/code> inside <code>onQueryStarted<\/code> for snappy UX; rollback on error.<\/p>\n<pre><code class=\"mono\">async onQueryStarted(arg, { dispatch, queryFulfilled }){\r\n  const patch = dispatch(api.util.updateQueryData('getUsers', undefined, (draft)=>{ draft.push(arg) }))\r\n  try{ await queryFulfilled } catch{ patch.undo() }\r\n}<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>28) Batching &#038; Performance<\/h3>\n<p>React 18 batches updates automatically in most cases. For custom batching of dispatches, you can still use <code>batch<\/code> from <code>react-redux<\/code> if needed.<\/p>\n<pre><code class=\"mono\">import { batch } from 'react-redux'<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>29) Error Handling Strategy<\/h3>\n<p>Normalize errors ({ message, code }) in thunks or RTKQ baseQuery. Surface via toasts\/slices. Avoid throwing non-serializable objects into state.<\/p>\n<pre><code class=\"mono\">const baseQuery = fetchBaseQuery({ baseUrl:'\/api' })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>30) Q&amp;A \u2014 \u201cThunks vs RTK Query?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Use RTK Query for CRUD APIs, caching, and invalidation. Use thunks for complex workflows that span multiple endpoints, business rules, or non-HTTP side effects.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 4: ARCHITECTURE, PATTERNS & INTEGRATIONS (31\u201340) ===================== --><\/p>\n<div class=\"section-title\">Section 4 \u2014 Architecture, Patterns &#038; Integrations<\/div>\n<div class=\"card bg-violet\">\n<h3>31) Feature Folder Structure<\/h3>\n<p>Organize by feature: each folder holds slice, selectors, components, and tests. Keeps boundaries clear and scaling manageable.<\/p>\n<pre><code class=\"mono\">features\/\r\n  auth\/\r\n    slice.ts\r\n    selectors.ts\r\n    Login.tsx<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>32) Selectors with Reselect<\/h3>\n<p>Memoized selectors compute derived data efficiently and prevent useless re-renders.<\/p>\n<pre><code class=\"mono\">import { createSelector } from '@reduxjs\/toolkit'\r\nconst selectItems = (s)=>s.cart.items\r\nexport const selectTotal = createSelector([selectItems], (items)=>items.length)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-green\">\n<h3>33) Form State: Local vs Redux<\/h3>\n<p>Keep transient form input in component state. Put in Redux when multiple pages depend on it (e.g., wizards), or for global persistence\/validation workflows.<\/p>\n<pre><code class=\"mono\">\/\/ Most forms: use local state or React Hook Form<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>34) Authentication<\/h3>\n<p>Store tokens carefully; prefer HTTP-only cookies over localStorage. Keep only necessary user profile data in Redux; avoid secrets in state.<\/p>\n<pre><code class=\"mono\">\/\/ on logout: dispatch(reset) across slices<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>35) Entity Adapters<\/h3>\n<p><code>createEntityAdapter<\/code> provides adapters with CRUD reducers and memoized selectors per entity set.<\/p>\n<pre><code class=\"mono\">const postsAdapter = createEntityAdapter({ sortComparer:(a,b)=&gt;b.date.localeCompare(a.date) })<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>36) Middleware Examples<\/h3>\n<p>Analytics, feature flags, performance logging, auth refresh, and WebSocket forwarding are classic custom middleware use cases.<\/p>\n<pre><code class=\"mono\">const analyticsMw = store =&gt; next =&gt; action =&gt; { \/* forward to analytics *\/; return next(action) }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan\">\n<h3>37) SSR &#038; Next.js<\/h3>\n<p>Preload data on the server and hydrate the store on the client. Avoid non-serializable values; seal initial state in HTML safely.<\/p>\n<pre><code class=\"mono\">const store = makeStore(preloadedState)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-lime\">\n<h3>38) Code Splitting<\/h3>\n<p>Inject reducers at runtime for lazy-loaded routes (e.g., with <code>redux-dynamic-modules<\/code> or manual injection patterns). Keep initial bundle small.<\/p>\n<pre><code class=\"mono\">\/\/ store.injectReducer('feature', featureReducer)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>39) Performance Anti-Patterns<\/h3>\n<p>Huge connected components, selectors returning new objects each time, overuse of global state, and non-memoized derived data. Fix with memoization, splitting components, entity adapters, and RTKQ.<\/p>\n<pre><code class=\"mono\">\/\/ Memoize selectors; use shallowEqual if needed<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald\">\n<h3>40) Q&amp;A \u2014 \u201cRedux vs Zustand\/Context?\u201d<\/h3>\n<p><span class=\"q\">Answer:<\/span> Redux offers a powerful ecosystem, DevTools, middleware, and RTK Query. Zustand or Context may be simpler for small apps; choose Redux for large teams, complex flows, and when you need time-travel debugging &#038; cache-aware data fetching.<\/p>\n<\/p><\/div>\n<p>      <!-- ===================== SECTION 5: TESTING, CHECKLIST & INTERVIEW (41\u201350) ===================== --><\/p>\n<div class=\"section-title\">Section 5 \u2014 Testing, Checklist &#038; Interview Q&amp;A<\/div>\n<div class=\"card bg-violet\">\n<h3>41) Testing Reducers<\/h3>\n<p>Reducers are pure; test input state + action \u2192 output state. No need for DOM.<\/p>\n<pre><code class=\"mono\">expect(cartReducer({items:[]}, addItem({id:'1'}))).toEqual({items:[{id:'1'}]})<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-blue\">\n<h3>42) Testing Thunks<\/h3>\n<p>Use MSW\/fetch-mocks to simulate network and assert dispatched actions. Keep thunks thin.<\/p>\n<pre><code class=\"mono\">await store.dispatch(fetchUsers()); expect(store.getState().users.list).toHaveLength(3)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-green\">\n<h3>43) Testing Selectors<\/h3>\n<p>Provide a sample state and assert the selector output. For memoized selectors, assert referential stability when inputs unchanged.<\/p>\n<pre><code class=\"mono\">expect(selectTotal({cart:{items:[1,2]}})).toBe(2)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-amber\">\n<h3>44) Testing Components<\/h3>\n<p>Wrap components with <code>&lt;Provider&gt;<\/code> using a test store. Use React Testing Library to assert rendered output and dispatch behavior.<\/p>\n<pre><code class=\"mono\">\/\/ render(&lt;Provider store={store}&gt;&lt;Cart\/&gt;&lt;\/Provider&gt;)<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-indigo\">\n<h3>45) Redux Persist (Optional)<\/h3>\n<p>Persist slices to storage (local\/session). Be selective\u2014never persist secrets; handle migrations and versioning.<\/p>\n<pre><code class=\"mono\">\/\/ redux-persist setup with a whitelist of slice keys<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-rose\">\n<h3>46) Error Boundaries &#038; Redux<\/h3>\n<p>Keep UI error boundaries at component level. Store normalized error info, not raw Error objects.<\/p>\n<pre><code class=\"mono\">state.error = { message: a.payload, code:'NET_FAIL' }<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-cyan tight\">\n<h3>47) Production Checklist<\/h3>\n<ul>\n<li>RTK store, slices, normalized entities<\/li>\n<li>Serializability enforced or exceptions documented<\/li>\n<li>Memoized selectors for heavy derivations<\/li>\n<li>RTK Query for CRUD APIs &#038; caching<\/li>\n<li>Strict typing (TS), unit &#038; integration tests<\/li>\n<li>Performance audits &#038; code splitting<\/li>\n<\/ul><\/div>\n<div class=\"card bg-lime\">\n<h3>48) Common Pitfalls<\/h3>\n<p>Hand-rolling Redux without RTK, putting everything in Redux (vs local state), non-serializable state, giant reducers, and failing to normalize data.<\/p>\n<pre><code class=\"mono\">\/\/ Prefer RTK + feature folders + adapters<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-orange\">\n<h3>49) Migration Tips (Legacy \u2192 RTK)<\/h3>\n<p>Wrap existing reducers with <code>combineReducers<\/code> inside <code>configureStore<\/code>, incrementally replace action creators with slices, and move fetch logic to thunks or RTKQ endpoints.<\/p>\n<pre><code class=\"mono\">\/\/ Start with store migration, then slice-by-slice refactor<\/code><\/pre>\n<\/p><\/div>\n<div class=\"card bg-emerald qa\">\n<h3>50) Interview Q&amp;A \u2014 20 Practical Questions (Expanded)<\/h3>\n<p><b>1) Why Redux Toolkit?<\/b> Cuts boilerplate, safe immutable updates via Immer, good defaults, and built-in async\/caching with RTK Query.<\/p>\n<p><b>2) What are reducers?<\/b> Pure functions (state, action) \u2192 new state; no side effects or mutations.<\/p>\n<p><b>3) When put state in Redux vs component?<\/b> Shared\/cross-page or business-critical state in Redux; transient\/local UI state stays local.<\/p>\n<p><b>4) How to avoid re-renders?<\/b> Use memoized selectors, split connected components, avoid selectors returning new objects, and normalize state.<\/p>\n<p><b>5) Thunk vs RTK Query?<\/b> RTKQ for standard data fetching\/caching; thunks for bespoke flows spanning multiple services or non-HTTP side effects.<\/p>\n<p><b>6) Serializability rules?<\/b> Keep actions\/state serializable for DevTools\/persistence; configure exceptions only when necessary.<\/p>\n<p><b>7) Entity adapter benefits?<\/b> Fast CRUD reducers, built-in selectors, and consistent normalized state pattern.<\/p>\n<p><b>8) prepare callback?<\/b> Preprocess payloads (IDs, timestamps) before reducer logic to keep reducers clean.<\/p>\n<p><b>9) How does Immer help?<\/b> Lets you write \u201cmutating\u201d code that produces immutable updates under the hood\u2014safer and faster to write.<\/p>\n<p><b>10) Why normalized state?<\/b> Avoid duplicate entities and tricky updates; O(1) lookups and easier memoization.<\/p>\n<p><b>11) Cache invalidation in RTKQ?<\/b> Tag types and IDs; mutations invalidate tags so queries refetch automatically.<\/p>\n<p><b>12) Error handling pattern?<\/b> Normalize to { message, code }; keep UI boundaries; avoid throwing non-serializable errors into state.<\/p>\n<p><b>13) SSR with Redux?<\/b> Preload state server-side, serialize safely, hydrate on client; avoid non-serializable values.<\/p>\n<p><b>14) Performance debugging?<\/b> Use React Profiler, Redux DevTools traces, memoized selectors, and split large connected components.<\/p>\n<p><b>15) Code splitting reducers?<\/b> Dynamically inject reducers for lazy routes; unregister when leaving if memory matters.<\/p>\n<p><b>16) Forms &#038; Redux?<\/b> Prefer local\/RHF; use Redux for multi-step shared state, server-synced drafts, or cross-tab persistence.<\/p>\n<p><b>17) Persisting state?<\/b> Whitelist slices; add migrations; never persist secrets\/PII.<\/p>\n<p><b>18) Testing thunks?<\/b> Mock network, assert dispatched actions &#038; final state. Keep thunks thin to simplify tests.<\/p>\n<p><b>19) Why actions should be minimal?<\/b> Smaller payloads reduce noise, improve DevTools clarity, and ease refactors.<\/p>\n<p><b>20) Alternatives to Redux?<\/b> Zustand, Jotai, Recoil, MobX, or React Query for server cache. Choose per app size, team familiarity, and needs.<\/p>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Redux Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20+ Interview Q&amp;A included Section 1 \u2014 Foundations 1) What is Redux? Redux is a <span class=\"readmore\"><a href=\"https:\/\/uplatz.com\/blog\/redux-pocket-book\/\">Read More &#8230;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2462,2471],"tags":[],"class_list":["post-4447","post","type-post","status-publish","format-standard","hentry","category-pocket-book","category-redux"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Redux Pocket Book | Uplatz Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/uplatz.com\/blog\/redux-pocket-book\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Redux Pocket Book | Uplatz Blog\" \/>\n<meta property=\"og:description\" content=\"Redux Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20+ Interview Q&amp;A included Section 1 \u2014 Foundations 1) What is Redux? Redux is a Read More ...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/uplatz.com\/blog\/redux-pocket-book\/\" \/>\n<meta property=\"og:site_name\" content=\"Uplatz Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Uplatz-1077816825610769\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-08-09T14:04:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-08-09T14:05:09+00:00\" \/>\n<meta name=\"author\" content=\"uplatzblog\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@uplatz_global\" \/>\n<meta name=\"twitter:site\" content=\"@uplatz_global\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"uplatzblog\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/\"},\"author\":{\"name\":\"uplatzblog\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/person\\\/8ecae69a21d0757bdb2f776e67d2645e\"},\"headline\":\"Redux Pocket Book\",\"datePublished\":\"2025-08-09T14:04:54+00:00\",\"dateModified\":\"2025-08-09T14:05:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/\"},\"wordCount\":1390,\"publisher\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\"},\"articleSection\":[\"Pocket Book\",\"Redux\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/\",\"name\":\"Redux Pocket Book | Uplatz Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#website\"},\"datePublished\":\"2025-08-09T14:04:54+00:00\",\"dateModified\":\"2025-08-09T14:05:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/redux-pocket-book\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Redux Pocket Book\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\",\"name\":\"Uplatz Blog\",\"description\":\"Uplatz is a global IT Training &amp; Consulting company\",\"publisher\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#organization\",\"name\":\"uplatz.com\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Uplatz-Logo-Copy-2.png\",\"contentUrl\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Uplatz-Logo-Copy-2.png\",\"width\":1280,\"height\":800,\"caption\":\"uplatz.com\"},\"image\":{\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Uplatz-1077816825610769\\\/\",\"https:\\\/\\\/x.com\\\/uplatz_global\",\"https:\\\/\\\/www.instagram.com\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/7956715?trk=tyah&amp;amp;amp;amp;trkInfo=clickedVertical:company,clickedEntityId:7956715,idx:1-1-1,tarId:1464353969447,tas:uplatz\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/uplatz.com\\\/blog\\\/#\\\/schema\\\/person\\\/8ecae69a21d0757bdb2f776e67d2645e\",\"name\":\"uplatzblog\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g\",\"caption\":\"uplatzblog\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Redux Pocket Book | Uplatz Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/","og_locale":"en_US","og_type":"article","og_title":"Redux Pocket Book | Uplatz Blog","og_description":"Redux Pocket Book \u2014 Uplatz 50 in-depth cards \u2022 Wide layout \u2022 Readable examples \u2022 20+ Interview Q&amp;A included Section 1 \u2014 Foundations 1) What is Redux? Redux is a Read More ...","og_url":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/","og_site_name":"Uplatz Blog","article_publisher":"https:\/\/www.facebook.com\/Uplatz-1077816825610769\/","article_published_time":"2025-08-09T14:04:54+00:00","article_modified_time":"2025-08-09T14:05:09+00:00","author":"uplatzblog","twitter_card":"summary_large_image","twitter_creator":"@uplatz_global","twitter_site":"@uplatz_global","twitter_misc":{"Written by":"uplatzblog"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/#article","isPartOf":{"@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/"},"author":{"name":"uplatzblog","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/person\/8ecae69a21d0757bdb2f776e67d2645e"},"headline":"Redux Pocket Book","datePublished":"2025-08-09T14:04:54+00:00","dateModified":"2025-08-09T14:05:09+00:00","mainEntityOfPage":{"@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/"},"wordCount":1390,"publisher":{"@id":"https:\/\/uplatz.com\/blog\/#organization"},"articleSection":["Pocket Book","Redux"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/","url":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/","name":"Redux Pocket Book | Uplatz Blog","isPartOf":{"@id":"https:\/\/uplatz.com\/blog\/#website"},"datePublished":"2025-08-09T14:04:54+00:00","dateModified":"2025-08-09T14:05:09+00:00","breadcrumb":{"@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/uplatz.com\/blog\/redux-pocket-book\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/uplatz.com\/blog\/redux-pocket-book\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/uplatz.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Redux Pocket Book"}]},{"@type":"WebSite","@id":"https:\/\/uplatz.com\/blog\/#website","url":"https:\/\/uplatz.com\/blog\/","name":"Uplatz Blog","description":"Uplatz is a global IT Training &amp; Consulting company","publisher":{"@id":"https:\/\/uplatz.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/uplatz.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/uplatz.com\/blog\/#organization","name":"uplatz.com","url":"https:\/\/uplatz.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/uplatz.com\/blog\/wp-content\/uploads\/2016\/11\/Uplatz-Logo-Copy-2.png","contentUrl":"https:\/\/uplatz.com\/blog\/wp-content\/uploads\/2016\/11\/Uplatz-Logo-Copy-2.png","width":1280,"height":800,"caption":"uplatz.com"},"image":{"@id":"https:\/\/uplatz.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Uplatz-1077816825610769\/","https:\/\/x.com\/uplatz_global","https:\/\/www.instagram.com\/","https:\/\/www.linkedin.com\/company\/7956715?trk=tyah&amp;amp;amp;amp;trkInfo=clickedVertical:company,clickedEntityId:7956715,idx:1-1-1,tarId:1464353969447,tas:uplatz"]},{"@type":"Person","@id":"https:\/\/uplatz.com\/blog\/#\/schema\/person\/8ecae69a21d0757bdb2f776e67d2645e","name":"uplatzblog","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7f814c72279199f59ded4418a8653ad15f5f8904ac75e025a4e2abe24d58fa5d?s=96&d=mm&r=g","caption":"uplatzblog"}}]}},"_links":{"self":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4447","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/comments?post=4447"}],"version-history":[{"count":1,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4447\/revisions"}],"predecessor-version":[{"id":4450,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/posts\/4447\/revisions\/4450"}],"wp:attachment":[{"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/media?parent=4447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/categories?post=4447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/uplatz.com\/blog\/wp-json\/wp\/v2\/tags?post=4447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}