reactjsreduxreact-reduxaxiosredux-thunk

Redux Thunk action with axios returning multiple values


I have a React app that uses redux-thunk and axios to fetch an API. The action fires successfully, but returns multiple payloads which means it is firing multiple times.

How can I make it fire only one time?

Code

Actions

import Axios from "axios";
import { fetchEnglishLeagueTable } from "./ActionTypes";

export function fetchEnglishTable() {
  var url = "https://api.football-data.org/v2/competitions/PL/matches";
  var token = "52c8d88969d84ac9b17edb956eea33af";
  var obj = {
    headers: { "X-Auth-Token": token }
  };
  return dispatch => {
    return Axios.get(url, obj)
      .then(res => {
        dispatch({
          type: fetchEnglishLeagueTable,
          payload: res.data
        });
      })
      .catch(e => {
        console.log("Cant fetch ", e);
      });
  };
}

Reducers

import { fetchEnglishLeagueTable } from "../actions/ActionTypes";
const initialState = {
  EnglishTable: {}
};

const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case fetchEnglishLeagueTable:
      return {
        ...state,
        EnglishTable: action.payload
      };
    default:
      return state;
  }
};

export default rootReducer;

Page

const League = props => {
  useEffect(() => {
    props.getLeagueTable();
  }, [props.leagueTable]);
  console.log(props.leagueTable);
  return <p>ihi</p>;
};
const mapStateToProps = state => ({
  leagueTable: state.EnglishTable
});
const mapDispatchToProps = dispatch => {
  return { getLeagueTable: () => dispatch(fetchEnglishTable()) };
};

export default connect(mapStateToProps, mapDispatchToProps)(League);

Store

import rootReducer from "./Reducer";
import thunk from "redux-thunk";

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

Here is what it returns Multiple Action firing


Solution

  • Just remove leagueTable from useEffect's dependency array, so it'll fetch them only once component is mounted. Because now you have a loop:

    Get leagues -> leagueTable updates -> useEffect sees that leagueTable changed in dependency array and calls to get leagues again and we've got a loop.

    const League = props => {
      useEffect(() => {
        props.getLeagueTable();
      }, []); // <~ no props.leagueTable here
      console.log(props.leagueTable);
      return <p>ihi</p>;
    };