A practical guide with example to learn Redux Toolkit implementation
Redux is a popular state management library for JavaScript applications, used for managing the state of your application in a single, centralized store. However, managing the state in Redux can become complex and verbose, especially as your application grows. This is where Redux Toolkit comes in to simplify the process and make state management in Redux easier and more intuitive.
In this blog post, we will introduce Redux Toolkit and walk through a practical example to demonstrate how it can help simplify the state management process.
What is Redux Toolkit?
Redux Toolkit is a set of tools and APIs that are designed to make it easier to work with Redux. It includes a variety of helpers and utilities that are aimed at reducing the boilerplate code that is required when using Redux. In addition, it provides a simple and intuitive API that makes it easier to create and manage actions, reducers, and middleware.
One of the key features of Redux Toolkit is its ability to automatically generate the action types and action creators for you, based on the names of the actions you define. This can save a significant amount of time and make your code more maintainable, as you don’t have to manually update action types and action creators whenever you make changes to your actions.
Another important feature of Redux Toolkit is its support for creating and managing asynchronous actions. This makes it easier to handle side-effects, such as fetching data from an API or updating a database, without having to write a lot of additional code.
Why use Redux Toolkit?
Redux Toolkit is a great choice for state management in your application because it makes it easier to manage the state of your application, while still providing the benefits of using Redux. Here are a few reasons why you should consider using Redux Toolkit:
- Simplified state management: Redux Toolkit simplifies the state management process by providing a set of tools and APIs that make it easier to create and manage actions, reducers, and middleware.
- Reduced boilerplate code: Redux Toolkit reduces the amount of boilerplate code that is required when working with Redux, making your code more concise and maintainable.
- Support for asynchronous actions: Redux Toolkit makes it easier to handle side-effects, such as fetching data from an API or updating a database, by providing built-in support for asynchronous actions.
Here is an example of how you can store a list of all Star Wars actor names from the SWAPI API using Redux Toolkit:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
const fetchActorNames = createAsyncThunk(
"actorNames/fetchActorNames",
async () => {
const response = await axios.get("https://swapi.dev/api/people");
return response.data.results.map((actor) => actor.name);
}
);
const actorNamesSlice = createSlice({
name: "actorNames",
initialState: {
names: [],
status: "idle",
error: null,
},
reducers: {},
extraReducers: {
[fetchActorNames.pending]: (state, action) => {
state.status = "loading";
},
[fetchActorNames.fulfilled]: (state, action) => {
state.status = "succeeded";
state.names = action.payload;
state.error = null;
},
[fetchActorNames.rejected]: (state, action) => {
state.status = "failed";
state.error = action.error.message;
},
},
});
export const { } = actorNamesSlice.actions;
export default actorNamesSlice.reducer;
export { fetchActorNames };
In the code above, we are using the createAsyncThunk
function from Redux Toolkit to create an asynchronous action that fetches the list of actor names from the SWAPI API. The fetchActorNames
function returns a Promise that resolves with the list of actor names, which is then dispatched as the result of the action.
We are also using the createSlice
function to create a slice of the store for our list of actor names. The initialState
object sets the initial state of the store to an empty array of names and an idle
status.
The extra reducers handle the different stages of the asynchronous action, updating the store’s state accordingly. When the action is pending
, the status is set to loading
. When the action is fulfilled
, the status is set to succeeded
and the list of actor names is stored in the state. If the action is rejected
, the status is set to failed
and the error message is stored in the state.
Here’s an example of how to display the fetchActorNames
action in your React component (App.js
in this case):
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchActorNames } from "./actorNamesSlice";
const App = () => {
const dispatch = useDispatch();
const { names, status, error } = useSelector((state) => state.actorNames);
useEffect(() => {
dispatch(fetchActorNames());
}, [dispatch]);
return (
<div>
{status === "loading" && <div>Loading...</div>}
{status === "succeeded" && (
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
)}
{status === "failed" && <div>Error: {error}</div>}
</div>
);
};
export default App;
In the code above, we are using the useSelector
and useDispatch
hooks from the react-redux
library to access the state of the store and dispatch actions, respectively. The useSelector
hook is used to retrieve the list of actor names, the status, and the error message from the store.
In the useEffect
hook, we dispatch the fetchActorNames
action when the component is mounted.
Finally, in the render function, we are using a conditional render to display the loading state, the list of actor names, or the error message based on the status of the action.
Finally, we are exporting the fetchActorNames
action creator and the reducer for the actor names slice.
Here’s an example of how you can set up the index.js
file to include the Redux store provider:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { configureStore } from "@reduxjs/toolkit";
import App from "./App";
import actorNamesReducer from "./actorNamesSlice";
const store = configureStore({
reducer: {
actorNames: actorNamesReducer,
},
});
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
In the code above, we are using the configureStore
function from Redux Toolkit to create a new store. The reducer
object passed to configureStore
includes the actorNamesReducer
that we exported from the actorNamesSlice.js
file.
We are also using the Provider
component from the react-redux
library to wrap the App
component and provide the store to all connected components. The store
prop on the Provider
component is set to the store that we created with configureStore
.
Finally, we are rendering the Provider
component to the root element in the DOM using ReactDOM.render
.
you can see the code repo for this example here: https://github.com/refarchdev/redux-toolkit-fetch-example
Here is a working demo of the code for you to play around:
Learn more about Redux Toolkit from here: https://redux-toolkit.js.org/introduction/getting-started