Friday, August 14, 2020

Fetch async data using Redux Thunk example

In the previous post we saw about setting up Redux Thunk for a React Redux application, in this post we shall see an example for fetching async data from an API call using axios and redux thunk, and update the store with the response from the API call.

Assuming that we have the required npm packages installed and the redux-thunk middleware configuration is setup as specified in the previous post we will go ahead with the actual implementation of redux-thunk and axios api calls.

We create 2 actions, first to set the locations array in the store and the 2nd to set a success/failure message.

export const SET_MESSAGE = "SET_MESSAGE";
export const GET_LOCATIONS = "GET_LOCATIONS";

export function SetMessage(value) {
  return {
      type: SET_MESSAGE,
      payload: {value}
    };
}

export function GetLocations(locations) {
  return {
      type: GET_LOCATIONS,
      payload: locations
    };
}

The redux reducer for the above actions will be as follows.

const initialState = {
    listMessage: '',
    locations: []
  };

export const listReducer = function (state = initialState, action) {
    switch (action.type) {
      case "SET_MESSAGE":
        return {
            ...state,
            listMessage: action.payload.value
          };
      case "GET_LOCATIONS":
        return {
            ...state,
            locations: action.payload
          };
      default:
        return state;
    }
  };

Next we will create a thunk action which will make the axios API call and dispatch the above actions to set the values in the store.

import axios from 'axios';
import * as appConfig from '../config';
import { GetLocations, SetMessage } from './actions';

export function FetchLocations() {
  const url = `${appConfig.LOCATION_API_URL}/GetAll`;
  console.log(url);
 
  return dispatch => {
    dispatch(SetMessage(`Loading..`));
    return axios.get(url)
      .then(res => res.data)
      .then(data => {
        console.log(data);
        dispatch(GetLocations(data));
        dispatch(SetMessage(`Locations loaded succesfully.`));
        return data;
      }).catch(error => {
        dispatch(SetMessage(`Unable to load Locations, Error: ${error}`));
      });
  };
}

Now we can call the thunk action from the react container component.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { SetMessage, GetLocations } from '../Redux/actions';
import { FetchLocations } from '../Redux/thunkActions';
import ListRedux from './ListRedux';

class ListReduxContainer extends Component {
   constructor() {
     super();
   }

   render() {
     return (
      <div>
        List
        <ListRedux {...this.props} />
      </div>
     );
   }
 }

function mapStateToProps(state) {
  return {
    listMessage: state.listReducer.listMessage,
    locations: state.listReducer.locations
  };
}
const mapDispatchToProps = dispatch => {
  return {
    setMessage: (value) => { dispatch(SetMessage(value)) },
    fetchLocations: () => { dispatch(FetchLocations()) }
  }
};

export default ListReduxContainer = connect(mapStateToProps, mapDispatchToProps)(ListRedux);

Finally we will call the dispatch functions from the actual UI component as follows.

import React, { Component } from 'react';

class ListRedux extends Component {
   constructor(props) {
     super(props);
   }

   componentDidMount() {
    this.props.fetchLocations();
  }

   render() {
     return (
      <div>
        <span className="Message">{this.props.listMessage}</span><br/>
        <table className="table">
          <thead className="thead-light">
            <tr>
              <th>#</th>
              <th>Floor</th>
              <th>Steet</th>
              <th>City</th>
              <th>Zip</th>
            </tr>
          </thead>
          <tbody>
            {
              this.props.locations.map(item =>
              <tr key={item.locationId}>
                <td>{item.locationId}</td>
                <td>{item.floor}</td>
                <td>{item.street}</td>
                <td>{item.city}</td>
                <td>{item.zip}</td>
              </tr>
              )}
            </tbody>
          </table>
      </div>
     );
   }
 }

export default ListRedux;

The output will be as follows, the data in the list is from the response of the axios API call.




Search Flipkart Products:
Flipkart.com

No comments: