In this article, we will explore how to use the Redux Toolkit in a React.js application to streamline state management and handle asynchronous operations, such as making API calls. Redux Toolkit’s createAsyncThunk simplifies the creation of asynchronous action creators, allowing us to efficiently fetch data from APIs. We will configure the Redux store with configureStore from Redux Toolkit and integrate it with React components to fetch and display data fetched from the API.
Output Preview:
 PrerequisitesApproach- Create a new React application using create-react-app. Install @reduxjs/toolkit, react-redux, and axios.
- Set up the Redux store using configureStore from @reduxjs/toolkit. Create a slice to handle user-related state, including fetching, adding, and removing users.
- Design React Create core components: App, UserList, and UserItem.Use useSelector to access state and useDispatch to dispatch actions.Implement useEffect to fetch users when the component mounts.
- Enhance App to include a form for adding new users. Add a delete button to UserItem for removing users.
- Connect form inputs and buttons to dispatch corresponding actions to update the state.
Steps to Setup ProjectStep 1: Create a reactJS application by using this command
npx create-react-app myapp Step 2: Navigate to project directory
cd myapp Step 3: Install the necessary packages/libraries in your project using the following commands.
npm install @reduxjs/toolkit axios npm install react-redux Project structure: Folder Structure The updated dependencies in package.json file will look like:
"dependencies": { "@reduxjs/toolkit": "^2.2.5", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.7.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-redux": "^9.1.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, Example: Implementation to show API calls while using reduce toolkit.
JavaScript
//App.js
import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsersAsync, addUser, removeUser } from '../userSlice';
import UserList from './UserList';
function App() {
const dispatch = useDispatch();
const users = useSelector((state) => state.user.users);
const loading = useSelector((state) => state.user.loading);
const error = useSelector((state) => state.user.error);
const [newUserName, setNewUserName] = useState('');
useEffect(() => {
dispatch(fetchUsersAsync());
}, [dispatch]);
const handleAddUser = () => {
dispatch(addUser({ id: users.length + 1, name: newUserName }));
setNewUserName('');
};
const handleRemoveUser = (id) => {
dispatch(removeUser(id));
};
return (
<div>
{loading && <p>Loading...</p>}
{error && <p>Error: {error}</p>}
<input
type="text"
value={newUserName}
onChange={(e) => setNewUserName(e.target.value)}
placeholder="Enter new user name"
/>
<button onClick={handleAddUser}>Add User</button>
<UserList users={users} onRemoveUser={handleRemoveUser} />
</div>
);
}
export default App;
JavaScript
// UserItem.js
import React from 'react';
function UserItem({ user, onRemoveUser }) {
return (
<li>
{user.name} <button onClick={
() => onRemoveUser(user.id)}>Delete</button>
</li>
);
}
export default UserItem;
JavaScript
//UserList.js
import React from 'react';
import UserItem from './UserItem';
function UserList({ users, onRemoveUser }) {
return (
<ul>
{users && users.map((user) => (
<UserItem key={user.id}
user={user} onRemoveUser={onRemoveUser} />
))}
</ul>
);
}
export default UserList;
JavaScript
// api.js
import axios from 'axios';
export const fetchUsers = async () => {
try {
const response =
await axios.get('https://jsonplaceholder.typicode.com/users');
return response.data;
} catch (error) {
throw error;
}
};
JavaScript
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './components/App';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
JavaScript
//store.js
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';
const store = configureStore({
reducer: {
user: userReducer,
},
});
export default store;
JavaScript
//userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchUsers } from './api';
export const fetchUsersAsync = createAsyncThunk(
'users/fetchUsers',
async () => {
const response = await fetchUsers();
return response;
}
);
const userSlice = createSlice({
name: 'user',
initialState: {
users: [],
loading: false,
error: null,
},
reducers: {
addUser: (state, action) => {
state.users.push(action.payload);
},
removeUser: (state, action) => {
state.users = state.users.filter(user => user.id !== action.payload);
},
},
extraReducers: (builder) => {
builder
.addCase(fetchUsersAsync.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchUsersAsync.fulfilled, (state, action) => {
state.loading = false;
state.users = action.payload;
})
.addCase(fetchUsersAsync.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
},
});
export const { addUser, removeUser } = userSlice.actions;
export default userSlice.reducer;
Step to Run Application: Run the application using the following command from the root directory of the project
npm start Output: Your project will be shown in the URL http://localhost:3000/
|