0
votes

I'm using the following:

  • "axios": "^0.15.3"
  • "react": "^15.4.2"
  • "react-redux": "^5.0.3"
  • "redux": "^3.6.0"
  • "redux-immutable": "^3.1.0"

I want to retreive data from the City of Boston's data portal. My goal is when a person goes to the "Property" screen, that component's ComponentWillMount() will invoke a sychronous API call to retreive the data BEFORE the compnonet is rendered. Please note I had all this working asychronously with redux-saga, but like I mentioned above, a user action triggers the retreival of data before that data is displayed in a component.

I'm getting the following error with my code:

Uncaught TypeError: Cannot read property 'type' of undefined

Here's what I have thus far:

  1. In my property.js (I removed code unrelated to the error):
//External Dependencies
import { connect } from "react-redux";

//Internal Dependencies
import { requestCityBosAPI } from "../../actions/citybosapi_action";

class Property extends React.Component {
  constructor(props) {
    super(props);
  };

  componentWillMount() {
    if (this.props.selectedAccount) {
      const citybosPID=this.props.selectedAccount.toJS().citybos_pid;
      console.log('Inside componentWillMount with citybospid=[' +citybosPID +"]");
      this.props.requestCityBosAPI(citybosPID);
    }
  };

...

Property.propTypes = {
  accounts: React.PropTypes.array.isRequired,
  selectedAccount: React.PropTypes.object
};

export default connect(
  state => ({
    accounts: state.get('accounts').get('json').get('accounts').toJS(),
    selectedAccount: state.get('accounts').get('selectedAccount')
  }),
  { requestCityBosAPI }
)(Property)
  1. In my citybosapi_action, I have:
//External Dependencies
import axios from 'axios';

//Internal Dependencies
import * as actionTypes from './action_types';

export function requestCityBosAPI(citybosPID) {
    let newcitybosPID='1000001021';
    // console.log('requestCityBosAPI citybosPID=[' + citybosPID + "]");
    const request = >   axios.get(`https://data.cityofboston.gov/resource/ti2c-bzzp.json?$where=PID=\"` + newcitybosPID + `\"`)
      .then(response => {
        console.log(response);
        if (response.status === 200) {
          return {
            type: actionTypes.OK_CITYBOSAPI,
            property2017: response.data,
            createDT: new Date().toUTCString()
       }
     }
   })

}

  1. And it my citybos_reducer, I have:
   //External Dependencies
   import Immutable from 'immutable';

   //Internal Dependencies
   import * as actionTypes from '../actions/action_types';

   const initialState = Immutable.Map({
     property2017: null,
     createDT: null,
     error: null,
     errorDT: null
   });

  console.log(initialState);

   export default (state = initialState, action) => {
     console.log(action);
     console.log("action.type=[" +action.type +"]");
     if (action.type === actionTypes.OK_CITYBOSAPI) {
        return state.merge({ //returning new states
          property2017: action.property2017,
          createDT: action.createDT
         })
     }
     else if (action.type === actionTypes.FAILED_CITYBOSAPI) {
       console.log('FAILED_CITYBOSAPI ' + new Date().toUTCString());
       return state.merge({ //returning new state
         error: action.error,
         errorDT: action.errorDT
       })
     }

     return state; //returns initial state
   }

In the Chrome Console, I get: enter image description here

You can see the error, and right after that I get the correct data printed to the console, BUT nothing happens with my reducer. All help is appreciated. I can see if I comment out the line:

const request = axios.get(https://data.cityofboston.gov/resource/ti2c-bzzp.json?$where=PID=\" + newcitybosPID + \")

Everything works properly from the action to the reducer...so I feel as a novice I'm using axios wrong. I even tried the following code wihtin my action and got the same error:

  export function requestCityBosAPI(citybosPID) {
    console.log('requestCityBosAPI citybosPID=[' + citybosPID + "]");
    axios.get(`https://data.cityofboston.gov/resource/ti2c-bzzp.json?$where=PID=\"` + citybosPID + `\"`)
      .then(function (response) {
        console.log(response);
        if (response.status === 200) {
          return {
            type: actionTypes.OK_CITYBOSAPI,
            property2017: response.data,
            createDT: new Date().toUTCString()
          }
        }
        else {
          return {
            type: actionTypes.FAILED_CITYBOSAPI,
            error: response.statusText,
            errorDT: new Date().toUTCString()
          }
        }
      })
      .catch(function (error) {
        console.log(error);

      });
  }

THANKS IN ADVANCE!

1

1 Answers

0
votes

Your action creator is not returning anything, so undefined is being dispatched to your store. The error is thrown when you try to read the property type of undefined in your reducer.

If you look at the action creator:

export function requestCityBosAPI(citybosPID) {
    let newcitybosPID='1000001021';
    // console.log('requestCityBosAPI citybosPID=[' + citybosPID + "]");
    const request = >   axios.get(`https://data.cityofboston.gov/resource/ti2c-bzzp.json?$where=PID=\"` + newcitybosPID + `\"`)
      .then(response => {
        console.log(response);
        if (response.status === 200) {
          return {
            type: actionTypes.OK_CITYBOSAPI,
            property2017: response.data,
            createDT: new Date().toUTCString()
       }
     }
   })
}

Then the only return statement is within the anonymous function passed to .then().

Axios as a library can only make synchronous calls - it is possible to make synchronous AJAX calls, but you have to ask yourself if this is really what you want? Your app will be completely unresponsive until the request resolves, which is generally a poor user experience.

I would use an asynchronous call and if this means that there is a short period where your component has no data, then you can just render a loading screen for that time. You could do this with whichever redux side-effect library you prefer, (redux-saga, redux-thunk etc.)