| Concept | Role |
|---|---|
| Store | Single source of truth — holds entire app state |
| Action | Plain object describing what happened { type, payload } |
| Reducer | Pure function: (state, action) => newState |
| Dispatch | Sends an action to the store |
| Selector | Reads state from store |
⚙️ Redux & Data Flow
reduxintermediate
⚙️Redux & Data Flow
Redux: predictable state container. Unidirectional flow — Action → Reducer → Store → View. Redux Toolkit is the modern standard.
Memory Trick
Redux flow: Dispatch an Action → Reducer handles it → Store updates → Component re-renders. One way, always.
Log in to track your mastery & progress
1️⃣ Core Concepts
2️⃣ Redux Toolkit (RTK)
RTK eliminates boilerplate with createSlice:
jsimport { createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: state => { state.value += 1; }, // Immer: safe mutations decrement: state => { state.value -= 1; }, incrementBy: (state, action) => { state.value += action.payload; } } }); export const { increment, decrement, incrementBy } = counterSlice.actions; export default counterSlice.reducer;
3️⃣ Async with Redux Thunk
js// createAsyncThunk handles loading/success/error states export const fetchUser = createAsyncThunk('user/fetch', async (id) => { const res = await fetch(`/api/users/${id}`); return res.json(); }); // In slice: extraReducers: (builder) => { builder .addCase(fetchUser.pending, state => { state.loading = true; }) .addCase(fetchUser.fulfilled, (state, action) => { state.user = action.payload; state.loading = false; }) .addCase(fetchUser.rejected, (state, action) => { state.error = action.error.message; state.loading = false; }); }
Was this helpful?
Test your Knowledge
2 questions to cement what you just learned.