2

In my react app I am using API calls which should be authenticated by a token. so the first call is for getToken and then storing token in the session, but whenever I start my project it always throws an error on first run it(the error on the title)but if I refresh it, everything works. Can somebody explain to me what I am missing is this a problem of Async Calls?

Below are some part of my code

1). This is where I call token and other required API for my page during load:

componentDidMount() {
 this.props.getToken('[email protected]','react007zxt');
  //sessionStorage.setItem('jwtToken', this.props.token);
   this.props.fetchStates();
   this.props.fetchVenues();
}

2). This is the action where I call fetch API:

import {
    FETCH_STATES,
    FETCH_VENUES
} from '../actions/types';

const token = sessionStorage.getItem('jwtToken');
const postheaders={
 'Content-Type': 'application/x-www-form-urlencoded'
};

export const getToken = (username,password) => dispatch=>{
        fetch('http://localhost:8001/api/getToken',{
          method: 'POST',
          headers: postheaders,
          body:JSON.stringify({username,password})
        })
            .then(res => res.json())
            .then(token =>{
              let str=JSON.stringify(token.token).replace(/"/g,"");
              sessionStorage.setItem('jwtToken',str);
            });
    };


export const fetchStates = () => dispatch => {
    fetch(`http://localhost:8001/api/states?token=${token}`)
        .then(res => res.json())
        .then(states => dispatch({
            type: FETCH_STATES,
            payload: states
        }));
};


export const fetchVenues=()=>dispatch=>{
       fetch('http://localhost:8001/api/venues')
           .then(res => res.json())
           .then(venues => dispatch({
               type: FETCH_VENUES,
               payload: venues
           })
           );
};

3). Below is the part of render where I am using it and getting an error on the first run :

const stateItems = this.props.states.map(data => (
           <option key={data.id} value = {data.state} > {data.state} </option>
       ));

             ));
  const venueItems = this.props.venues.map(venue => (
                           <option key={venue.id} value = {venue.id} > {venue.college_name} </option>
                       ));

Edit 1: Problem is with token getting set in session store which is not available for the first API calls of states and venues.

http://localhost:8001/api/states?token=null 400 (Bad Request)
14
  • 1
    You are making an API call in componentDidMount and so on first render you data states and venues will not be available, provide an undefined check before using these values Commented Nov 19, 2018 at 7:00
  • 1
    What exactly is the behaviour, can you please elaborate on that Commented Nov 19, 2018 at 8:53
  • 1
    okkk, from the error it seems that states is being provided as an object, instead it should be an error. Either you have initialised it incorrectly in component state or the API is responding with an object and you need to convert it into an array in order to use map Commented Nov 19, 2018 at 9:00
  • 1
    could be because in initialisation you set state to empty object while the API responds with data and state is set to an array which is expected Commented Nov 19, 2018 at 9:09
  • 1
    If token can be received synchronously, retrieve it in constructor else have a loading state and set loading to false once you receive token Commented Nov 20, 2018 at 7:29

1 Answer 1

3

On the first render, the api call is being made, so it's most likely that when you are trying to access this.props.states it is undefined or empty.

A conditional to check it's availability should work for you, something on the lines of this.props.states && this.props.states.map(..)

You'll have to make sure other things work fine if this doesn't render until this.props.states gets populated with values.

Hope this helps :)

Sign up to request clarification or add additional context in comments.

1 Comment

Ho to check condition on this.props.states && this.props.states.map(..), like is it undefined?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.