Redux Toolkit is the officially recommended toolset for simplifying Redux development. It incorporates preset best practices, making it easier to create and manage Redux state.
1. Creating a Store
Use the configureStore
function to create a Redux store, which automatically configures middleware, such as redux-thunk
for handling asynchronous operations.
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer,
});
export default store;
2. Creating Reducer Slices
Redux Toolkit provides the createSlice
API to create manageable state slices and automatically generate corresponding action creators.
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
reset: () => 0,
},
});
export const { increment, decrement, reset } = counterSlice.actions;
export default counterSlice.reducer;
3. Dispatching Actions
In React components, use the useDispatch
and useSelector
hooks from react-redux
to dispatch actions and access state.
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement, reset } from './counterSlice';
function Counter() {
const dispatch = useDispatch();
const count = useSelector((state) => state.counter);
return (
<div>
<button onClick={() => dispatch(increment())}>+</button>
<p>{count}</p>
<button onClick={() => dispatch(decrement())}>-</button>
<button onClick={() => dispatch(reset())}>Reset</button>
</div>
);
}
export default Counter;
Middleware Support
Redux Toolkit allows easy addition of custom middleware, such as redux-thunk
, for handling asynchronous operations.
import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer,
middleware: [thunk],
});
Performance Optimization
Use createAsyncThunk
to create action creators for handling asynchronous operations, which automatically manage pending, fulfilled, and rejected states.
import { createAsyncThunk } from '@reduxjs/toolkit';
export const fetchUser = createAsyncThunk(
'users/fetchUser',
async () => {
const response = await fetch('https://api.example.com/user');
const data = await response.json();
return data;
}
);
Writing Selectors
Use createSelector
(typically from the reselect
library) to create efficient computed properties that recompute only when dependencies change.
import { createSelector } from 'reselect';
const selectUser = (state) => state.users.user;
const selectTotal = createSelector(
[selectUser],
user => user && user.totalPoints
);
export const selectTotalPoints = selectTotal;
Immutability in Redux
Redux Toolkit uses the immer
library by default, allowing direct state modifications in reducers while automatically handling immutable updates.
import { createSlice } from '@reduxjs/toolkit';
const todoSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
addTodo: (state, action) => {
// Directly modify state, immer handles immutability
state.push({ text: action.payload, completed: false });
},
toggleTodo: (state, action) => {
state[action.payload.index].completed = !state[action.payload.index].completed;
},
},
});
export const { addTodo, toggleTodo } = todoSlice.actions;
export default todoSlice.reducer;
Automatic Reducer Matching
When importing a slice’s reducer, Redux Toolkit automatically adds it to the store’s reducer object, eliminating the need for manual merging.
Code Splitting
For large applications, consider splitting state slices into multiple files and loading them on-demand to achieve code splitting.
Middleware Integration
Redux Toolkit makes it easy to add and manage multiple middlewares, such as logging or error handling.
Testing
Action creators and reducers created with createSlice
are easier to unit test due to their clear logic.
Using TypeScript
Redux Toolkit integrates well with TypeScript, providing type safety for action creators, reducers, and the entire store.
CombineReducers
While createSlice
simplifies state slice creation and management, you can still use combineReducers
to combine multiple slices for more complex application structures.
Using RTK Query
Redux Toolkit provides the createApi
function for managing API requests, similar to Apollo Client’s GraphQL queries. It handles caching, automatic retries, and subscriptions.
Performance Monitoring
Redux Toolkit integrates with Redux DevTools for convenient state change monitoring, including time-travel debugging and snapshot comparisons, which are invaluable for debugging and performance optimization.
Error Handling
Handle errors in asynchronous operations using the second parameter of createAsyncThunk
, improving user experience.
export const fetchUser = createAsyncThunk(
'users/fetchUser',
async (_, thunkAPI) => {
try {
const response = await fetch('https://api.example.com/user');
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json();
} catch (error) {
// Errors are automatically handled and returned to the rejected case
return thunkAPI.rejectWithValue(error.message);
}
}
);
Normalizing State Shape
For complex data structures, consider normalizing the state shape to reduce redundancy and improve query performance. The normalizr
library can assist with this task.
Reducer Composition
You can use other reducer functions within a slice to compose complex business logic.
Middleware for Side Effects
Redux Toolkit allows middleware to handle side effects, such as network requests, scheduled tasks, or event subscriptions.
Reducer Logic Refactoring
If your application requires refactoring, you can easily split a large reducer into smaller, reusable parts and combine them using combineReducers
.
Optimistic Updates
Use Redux Toolkit to implement optimistic updates, displaying expected results before data is actually updated to enhance user experience.
Code Generation
In large projects, consider using code generation tools like redux-starter-kit
or custom scripts to automate the creation of slices and action creators.
Redux Toolkit provides numerous tools and best practices to help developers manage React application state more efficiently. By leveraging these features, you can build more robust and maintainable projects. In practice, continuous learning and exploration to find the best approach for your project’s needs is key to improving development efficiency.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.