Redux - thunk API call doesn't work

Redux - thunk API call doesn't work
0

#1

Hi. I’m doing simple test assignment - but got stuck tying to make redux get data from api and pass it as props.
Instead of object with data - I get an empty object
Here’s my component code:

import React, { Component } from "react";
import PropTypes from 'prop-types'
import { connect } from 'react-redux';
import { getAPIDetails } from '../redux/actionCreators';

class ProductsList extends Component {

  componentDidMount() {
    if (!this.props.products) {
      this.props.getAPIData();
    }
  }

  render() {
    return (
      <div className="landing">
        {JSON.stringify(this.props.products, null, 4)}
      </div>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  const apiData = state.apiData[ownProps.products] ? state.apiData[ownProps.products] : {};
  return {
    products: apiData.products
  };
};

const mapDispatchToProps = (dispatch, ownProps) => ({
  getAPIData() {
    dispatch(getAPIDetails(ownProps.match.params.category));
  }
});

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

ProductsList.defaultProps = {
  getAPIData: null,
  products: [{}]
};
ProductsList.propTypes = {
  products: PropTypes.arrayOf(PropTypes.object),
  getAPIData: PropTypes.func
};

Here’s a reducer:

import { combineReducers } from 'redux';
import { SET_SEARCH_TERM, ADD_API_DATA } from './actions';

const searchTerm = (state = '', action) => {
  if (action.type === SET_SEARCH_TERM) {
    return action.payload;
  }
  return state;
};

const apiData = (state = {}, action) => {
  if (action.type === ADD_API_DATA) {
    return Object.assign({}, state, { [action.payload.products]: action.payload });
  }
  return state;
};

const rootReducer = combineReducers({ searchTerm, apiData });

export default rootReducer;

Here’s an action:

export const SET_SEARCH_TERM = 'SET_SEARCH_TERM';
export const ADD_API_DATA = 'ADD_API_DATA';

And here’s an action creator:

export function setSearchTerm(searchTerm) {
  return { type: SET_SEARCH_TERM, payload: searchTerm };
}

export function addAPIData(apiData) {
  return { type: ADD_API_DATA, payload: apiData };
}

export function getAPIDetails(category) {
  return (dispatch) => {
    axios
      .get(`http://localhost:3000/${category}`)
      .then(response => {
        dispatch(addAPIData(response.data));
      })
      .catch(error => {
        console.error('axios error', error); // eslint-disable-line no-console
      });
  };
}

#2

It’s very difficult to debug applications by just reading their code, so to get the best help, put this into a CodePen project or something. However, there are a couple of things that jump out at me. First, you’re calling dispatch from an action creator. This is an antipattern as it leads to unpredictable behavior. Second, your action creator needs to return a plain object. The way to do AJAX with Redux is to use middleware with Redux-thunk (so you’re on the right track). There are more details in the Redux documentation, and I have an example project on Codepen - it doesn’t use React, but you can still get an idea of how AJAX should work.