In recent updates to Redux Toolkit, the way we define reducers has evolved. The traditional object notation for createReducer
has been replaced by a more flexible and powerful builder callback notation. This change is designed to offer better TypeScript support and more control over reducer logic. Let's dive into the difference and see how to upgrade your code.
The Old Way: Object Notation
Previously, we could define our reducers using an object where keys were action types and values were the corresponding reducer functions. Hereβs an example:
import { createReducer } from '@reduxjs/toolkit';
let id = 0;
const tasksReducer = createReducer([], {
ADD_TASK: (state, action) => {
state.push({
id: ++id,
task: action.payload.task,
completed: false,
});
},
REMOVE_TASK: (state, action) => {
const index = state.findIndex((task) => task.id === action.payload.id);
if (index !== -1) {
state.splice(index, 1);
}
},
COMPLETE_TASK: (state, action) => {
const index = state.findIndex((task) => task.id === action.payload.id);
if (index !== -1) {
state[index].completed = true;
}
},
});
export default tasksReducer;
The New Way: Builder Callback Notation
With the new builder callback notation, we define reducers using a builder pattern. This approach provides a more structured and scalable way to handle actions, especially in larger applications.
import { createReducer } from '@reduxjs/toolkit';
let id = 0;
const tasksReducer = createReducer([], (builder) => {
builder
.addCase('ADD_TASK', (state, action) => {
state.push({
id: ++id,
task: action.payload.task,
completed: false,
});
})
.addCase('REMOVE_TASK', (state, action) => {
const index = state.findIndex((task) => task.id === action.payload.id);
if (index !== -1) {
state.splice(index, 1);
}
})
.addCase('COMPLETE_TASK', (state, action) => {
const index = state.findIndex((task) => task.id === action.payload.id);
if (index !== -1) {
state[index].completed = true;
}
});
});
export default tasksReducer;
Top comments (0)