Create a React app through Vite.
npm create vite@latest
Trim out the excess code from the vite boiler plate.
In the "src" directory, create a folder named "redux",
In the redux folder, create a javascript file named "store.js",
In the store.js file, configure the store as shown below.
import { configureStore } from "@reduxjs/toolkit";
export const store = configureStore({
reducer:{
//your reducers will go here later
}
})
In the redux folder, create a folder named "slice",
In this folder, we will create slices for different functionalities in our project.
For example, A Todo App will have a slice named "todoSlice.js",
In this todo slice, we will be calling the API to fetch the todos.
In todoSlics.js, write the following code:.
import { createSlice } from "@reduxjs/toolkit";
//this will be the initial state of the store
const initialState= {
isLoaing: false,
todos: [],
isError: false
}
//name is imortant
const todoSlice = createSlice({
name: "todo",
initialState,
reducers:{
},
//we will see about this extra reducers later in the blog
extraReducers: () => {}
})
export default todoSlice.reducer;
In the store.js file, import this slice, and the reducers will be responsible for talking to the store.
import { configureStore } from "@reduxjs/toolkit";
//we exported default so dont use curly braces here
//to imprt the reducer
import todoReducer from "./slice/todoSlice"
export const store = configureStore({
reducer: {
// this key value pair is important to remember while using
//useSelector hook to access the state
todo: todoReducer,
}
})
in main.jsx file, make the following changes to apply redux to the project:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
//imported for redux
import { Provider } from 'react-redux'
import { store } from './redux/store.js'
ReactDOM.createRoot(document.getElementById('root')).render(
// the store passed as prop to the provider
//is the store we created in redux folder
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>,
</Provider>
)
This concludes our boiler plate for any project that wants to use redux-toolkit
Now comes the API calling part.
This is the url we are going to use for API
https://dummyjson.com/todos?limit=5
This is the data we are getting. We can change the limit up to 100 or not give this limit parameter to receive the default 30 todos.
"todos": [
{
"id": 1,
"todo": "Do something nice for someone I care about",
"completed": true,
"userId": 26
},
{
"id": 2,
"todo": "Memorize the fifty states and their capitals",
"completed": false,
"userId": 48
},
{
"id": 3,
"todo": "Watch a classic movie",
"completed": false,
"userId": 4
},
{
"id": 4,
"todo": "Contribute code or a monetary donation to an open-source software project",
"completed": false,
"userId": 48
},
{
"id": 5,
"todo": "Solve a Rubik's cube",
"completed": false,
"userId": 31
}
]
In our project, we will give a button to the user to fetch todos, put the todos in our store through the useDispatch() hook, and access the todos through the Selector() hook.
For the API calling, we will be using a method named createAsyncThunk in the todoSlice file.
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
//this will be the initial state of the store
const initialState = {
isLoaing: false,
todos: [],
isError: false
}
//action to fetch the todos
export const fetchTodos = createAsyncThunk("fetchTodos",
//async call back function for API calling
async () => {
const response = await fetch('https://dummyjson.com/todos?limit=5')
return response.json()
}
)
//name is imortant
const todoSlice = createSlice({
name: "todo",
initialState,
reducers: {
},
//extra reducers is a callback function that will handle
//the three stages of a promise in javascript
//PENDING , FULFILLED , REJECTED
extraReducers: (builder) => {
builder.addCase(fetchTodos.pending, (state) => {
state.isLoaing = true
})
builder.addCase(fetchTodos.fulfilled, (state, action) => {
state.isLoaing = false,
state.todos = action.payload
})
builder.addCase(fetchTodos.rejected, (state, action) => {
console.log("error", action.payload)
state.isError = true
})
}
})
export default todoSlice.reducer;
Now in the App.jsx file, you can access the state and actions through the useDisapactch() and useSelector() hooks, as follows:.
import { useDispatch, useSelector } from "react-redux"
import { fetchTodos } from "./redux/slice/todoSlice"
function App() {
//to dispatch the fetchTodos method
const dispatch = useDispatch()
// to access the fetched todos from the store
const { todos } = useSelector(state => state.todo)
console.log(todos)
return (
<>
{/* on click of this button the todos will be fetched */}
<button
onClick={() => dispatch(fetchTodos())}
>Fetch the Todos</button>
</>
)
}
export default App
Like this, you can do API calling in the Redux Toolkit efficiently.
Thank you for reading this far.