Making API calls in React using Redux-Thunk
Tags: react, redux, javascript
Published: 2020-03-25 06:59:12

Deep dive into react-redux with a thunk as a middleware to make the API calls on-load that makes your app faster.

# When working with Redux, you will need three main things:

1. Actions: these are nothing but the objects that should have two properties, one describing the type of action, and one describing what should be changed in the app state.

2. Reducers: these are functions that implement the behavior of the actions. They change the state of the app, based on the action dispatched.

3. Store: it brings and connects the actions and reducers together, holding and changing the state for the whole app — there is only one store.

**Redux lets your React components read data from a Redux store, and dispatch actions to the store to update data using reducers.**

Let's deep dive into the redux:

* npm i **redux** **redux-thunk** **redux-persist** **redux-logger**

redux > actions > **actions.js**
```javascript
export const GET_USERS = "GET_USERS";
```
redux > actions > **taskAction.js**
```javascript
import {
    GET_USERS,
} from "./actions";

export const GetUsers = () => {
    console.log("GetUsers");
    
    return dispatch => {
        console.log("GetUsers dispatch");

        axios.get(`https://reqres.in/api/users`)
        .then(res => {
            const persons = res.data;
            
            dispatch({
                type: GET_USERS,
                users: response
            });
        })
    };
};

export const AddUser = (params) => {
    console.log("AddUser");
    
    return dispatch => {
        console.log("Add User dispatch");
    
        axios.post(`https://reqres.in/api/users`, {params})
        .then(response => {
            console.log(response);

            axios.get(`https://reqres.in/api/users`)
            .then(res => {
                console.log(res);
                
                dispatch({
                    type: GET_USERS,
                    users: response
                });
            })
        })
    };
};
```
redux > reducers > **index.js**
```javascript
import { combineReducers } from 'redux';
import TaskReducer from './taskReducer'; //add this line

const rootReducer = combineReducers({
  task:TaskReducer  //add taskreducer and name is task for future use.
  });
export default rootReducer;
```
redux > reducers > **taskReducer.js**
```javascript
import { 
    GET_USERS,
  } from "../actions/actions";
  
  const INITIAL_STATE = {
    Users: [],
    loading : false,
  };
  
  export default (state = INITIAL_STATE, action) => {
    //  console.log("task reducer"  , action);
  
    switch (action.type) {
      case GET_USERS: {
        return {
          ...state,
          Users: action.users,
          loading: false
        };
      }
      default:
        return state;
    }
  };
```
redux > store > **store.js**
```javascript
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from '../reducers/index';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'

const persistConfig = {
   key: 'root',
   storage: storage,
}

const middlewares = [thunk];

if (process.env.NODE_ENV === `development`) {
   const { logger } = require(`redux-logger`);

   middlewares.push(logger);
}

const persistedReducer = persistReducer(persistConfig, reducers)

export default () => {
   let store = createStore(
     persistedReducer,
     applyMiddleware(...middlewares)
   )
   
   let persistor = persistStore(store)
   return { store, persistor }
}
```
**App.js** should be look something like this,
```javascript
import {
  GetUsers
} from "./app/redux/actions/taskAction";
 
 class App extends React.Component {

  constructor(props) {
      super(props);

      this.state = {
      }
  }

  componentDidMount() {
    // making all API calls and store in the redux-store
    this.props.GetUsers();
  }
  
  render() {
    console.log("this.props.tasksss ", this.props.Loading);
    return (
      <div>
      ...
      </div>
    );
  }
}

const mapStateToProps = state => ({
  Loading: state.task.loading
});

const mapDispacthToProps = dispatch => {
  return {
    GetUsers: () => dispatch(GetUsers())    
  };
  
};
export default connect(
  mapStateToProps,
  mapDispacthToProps
)(App);
```
Apps main **index.js** should be look something like this,
```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";

import './index.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/lib/integration/react";
import configureStore from "./app/redux/store/store";

let { store, persistor } = configureStore();

ReactDOM.render(
    <BrowserRouter>
        <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>
                <App />
            </PersistGate>
        </Provider>,
    </BrowserRouter>, 
    document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
```

**HomeComponents.js** from where you **get** the Users from the **redux** store and add a new User using **dispatch**
```javascript
import React from 'react';
import { connect } from "react-redux";

import { AddUser } from "../../redux/actions/taskAction";

class Home extends React.Component {

    constructor(props) {
      super(props);
    }
  
  // creating new user using Redux-Thunk
    addNewUser = () => {
        let data = {
            "name": "muhammad awais",
            "job": "developer"
        }

        this.props.submit(
            data
        );
    }

    render() {
      
        // getting users from redux store
        console.log("this.props.Users : ",this.props.Users);
        
        return (
            <div>
                ...
            </div>
        );
    }
}

const mapStateToProps = state => ({
    Users: state.task.Users
});

const mapDispacthToProps = dispatch => {
    return {
        submit: (data) => {
            dispatch(AddUser(data))
        }
    };
};
// export default withStyles(styles)(ProductList);
export default connect(
    mapStateToProps,
    mapDispacthToProps
)(Home);
```
**That’s all. for now. I will release some new articles in detail.**