How to call APIs in React Redux ?
Tags: react, redux, javascript
Published: 2021-05-31 15:36:31

Hi, Today we are going to build simple **React** application which call the get request and show the data. We are using **Redux** for this application, Redux is a state management library for javascript applications. If you are not familiar with Redux, I highly recommend you to read the Redux fundamentals from Redux documentation. For better understanding watch the **demo video**.

So let's start coding...

**Demo Video**
{%youtube h-Cfm9bNL0w %}
[Source Code](https://github.com/sk-Jahangeer/react-redux-api)

**Project Structure**
![react redux api](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k860118zorc3dto4aa8g.png)
**Create React App**
```javascript
$ npx create-react-app react-redux-api
$ cd react-redux-api
$ npm start
```
**Install Dependencies**

**Redux :** It's a State management library for javascript applications.
**Axios :** It's a promise-based HTTP client that supports an easy-to-use API.
**React-Redux :** React Redux is the official React Ui bindings layer for Redux.
**@reduxjs/toolkit :** For writing clean redux code and it comes with most widly used Redux addons.

**Create API Actions**
src/store/api.js
```javascript
import { createAction } from "@reduxjs/toolkit";

export const apiCallBegan = createAction("api/callBegan");
export const apiCallSucess = createAction("api/callSuccess");
export const apiCallFailed = createAction("api/callFailed");
```
**Create API Middleware**
src/store/middleware/api.js
```javascript
import axios from "axios";
import * as actions from "../api";

const api =
    ({ dispatch }) =>
    (next) =>
    async (action) => {
        if (action.type !== actions.apiCallBegan.type) return next(action);

        const { url, method, data, onStart, onSuccess, onError } =
            action.payload;

        if (onStart) dispatch({ type: onStart });

        next(action);

        try {
            const response = await axios.request({
                baseURL: "https://jsonplaceholder.typicode.com",
                url,
                method,
                data,
            });
            // General
            dispatch(actions.apiCallSucess(response.data));
            // Specific
            if (onSuccess)
                dispatch({ type: onSuccess, payload: response.data });
        } catch (error) {
            // General
            dispatch(actions.apiCallFailed(error.message));
            // Specific
            if (onError) dispatch({ type: onError, payload: error.message });
        }
    };

export default api;
```
Redux already has an async middleware function called **Redux "Thunk" middleware**. The thunk  middleware allows us to write functions that get **dispatch** and **getState** as arguments. For better understanding read [documentation](https://redux.js.org/tutorials/fundamentals/part-6-async-logic).

**Create Actions & Reducers for Posts**
src/store/posts.js
```javascript
import { createSlice } from "@reduxjs/toolkit";
import { apiCallBegan } from "./api";

const slice = createSlice({
    name: "posts",
    initialState: {
        list: [],
        loading: false,
    },

    reducers: {
        postsRequested: (posts, action) => {
            posts.loading = true;
        },

        postsReceived: (posts, action) => {
            posts.list = action.payload;
            posts.loading = false;
        },

        postsRequestFailed: (posts, action) => {
            posts.loading = false;
        },
    },
});

export default slice.reducer;

const { postsRequested, postsReceived, postsRequestFailed } = slice.actions;

const url = "/posts";

export const loadposts = () => (dispatch) => {
    return dispatch(
        apiCallBegan({
            url,
            onStart: postsRequested.type,
            onSuccess: postsReceived.type,
            onError: postsRequestFailed.type,
        })
    );
};
```
**Configure Store**
```javascript
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import reducer from "./posts";
import api from "./middleware/api";

export default function store() {
    return configureStore({
        reducer,
        middleware: [...getDefaultMiddleware(), api],
    });
}
```
**Posts Component**
src/components/posts.js
```javascript
import { useDispatch, useSelector } from "react-redux";
import { loadposts } from "../store/posts";
import { useEffect } from "react";

const Posts = () => {
    const dispatch = useDispatch();
    const posts = useSelector((state) => state.list);

    useEffect(() => {
        dispatch(loadposts());
    }, [dispatch]);

    return (
        <div>
            <h1>Posts</h1>
            <ul>
                {posts.map((post) => (
                    <li key={post.id}>{post.title}</li>
                ))}
            </ul>
        </div>
    );
};

export default Posts;
```
**App.js**
```javascript
import { Provider } from "react-redux";
import configureStore from "./store/configureStore";
import Posts from "./components/posts";
import "./App.css";

const store = configureStore();

const App = () => {
    return (
        <Provider store={store}>
            <Posts />
        </Provider>
    );
};

export default App;
```
That's it, run the project on your local server. check APIs are working or not. If you found any mistakes or making code better please let me know. I hope you have learned something.

**If you like this post, support me on my youtube channel it inspire me a lot.**

**Thank You...**