Home
Daily
Redux Toolkit
November 02, 2025
1 min

Table Of Contents

01
Core Concepts
02
Handle Async Logic
03
Redux-Saga
04
Redux-Saga Example

Redux Toolkit (RTK) is the official, recommended way to write Redux logic. It keeps Redux’s core ideas while removing unnecessary boilerplate and enforcing best practices.

Image

Core Concepts

Flow: UI → Action → Reducer → Store → UI

1. Define a slice

const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment(state) {
state.value++;
},
},
});

RTK auto-creates:

  • Action types → "counter/increment"
  • Action creators → increment()

2. Configure the store

const store = configureStore({
reducer: { counter: counterSlice.reducer },
});

RTK:

  • Combines reducers
  • Adds default middleware
  • Enables DevTools

3. UI dispatches actions

dispatch(counterSlice.actions.increment());

4. Reducer updates state (via Immer)

state.value++; // looks mutable, stays immutable

5. Store saves new state → UI re-renders

Components subscribed with useSelector get updated automatically.

Handle Async Logic

Dispatch thunk → pending → (API call) → fulfilled OR rejected → state update → UI re-render

// dispatch(fetchData());
const slice = createSlice({
name: "data",
initialState: { data: null, loading: false, error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchData.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchData.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(fetchData.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message || "Failed to fetch";
});
},
});

RTK auto-dispatches:

  1. data/fetch/pending
  2. data/fetch/fulfilled
  3. data/fetch/rejected

Handled in slice extraReducers.

Redux-Saga

Redux-Saga is a Redux middleware for handling complex async side effects like API calls, delays, retries, concurrency, and cancellation.

It uses generator functions (function*) to:

  • Pause/resume with yield
  • Write async logic in a sync-looking way
  • Control concurrency, cancellation, sequencing

Core Effects

  1. call(fn, ...args)
  • Runs a function (e.g., API call)
  • Blocking: waits for result
  1. put(action)
  • Dispatches a Redux action
  1. takeEvery
  • Runs saga for every action
  • No cancellation
  1. takeLatest
  • Runs only the latest
  • Cancels previous
  1. takeLeading
  • Runs only the first
  • Ignores others until done

Parallel Effects

yield all([
call(fetchUser),
call(fetchPosts),
call(fetchComments),
])

Runs effects concurrently.

Redux-Saga Example

// sagas.ts
function* fetchPokemonAllWorker(): SagaIterator {
try {
const list: { id: number; name: string }[] =
yield call(api.fetchPokemonListApi)
const fullList: PokemonFull[] = yield all(
list.map(p => call(fetchPokemonFullWorker, p))
)
yield put(fetchPokemonAllSuccess(fullList))
} catch (e) {
yield put(fetchPokemonAllFailure('Failed to load Pokémon'))
}
}
function* fetchPokemonFullWorker(
pokemon: { id: number; name: string }
): SagaIterator<PokemonFull> {
const detail: any = yield call(api.fetchPokemonDetail, pokemon.name)
const [species, types, abilities]: [any, any[], any[]] = yield all([
call(api.fetchByUrl, detail.species.url),
all(detail.types.map((t: any) => call(api.fetchByUrl, t.type.url))),
all(detail.abilities.map((a: any) =>
call(api.fetchByUrl, a.ability.url)
)),
])
return {
id: detail.id,
name: detail.name,
detail,
species,
types,
abilities,
}
}
export default function* pokemonSaga(): SagaIterator {
yield takeLatest(fetchPokemonAll.type, fetchPokemonAllWorker)
}

Tags

#redux

Share

Related Posts

State Management
React Query
January 17, 2026
1 min
© 2026, All Rights Reserved.
Powered By

Social Media

githublinkedinyoutube