9

Following the React AJAX example i have created a JSX file which purpose is to fetch and render a movie. For all i know, i am doing everything right here.

When i console.log the data in my render function i get 2 results:

  • Undefined
  • Object (which is the one i need, so this one is perfect)

How can i filter out the Undefined row without doing some if/else logic in my render function? Iterating over the result will, of course, result in an error the first time, which will crash my application.

What's the best way to handle this?

EDIT: Maybe the app gets rendered before the Axios call is done in which case i am forced to do an if/else statement?

Heres my JSX file:

import React from "react";
import axios from "axios";

export default class NetflixHero extends React.Component {
 constructor() {
    super();
    this.state = {
      movie: []
    }
 }
}

componentDidMount() {
  const apiKey = 'xxxxxxxx';
  let requestUrl = 'https://api.themoviedb.org/3/' + this.props.apiAction + '&api_key=' + apiKey;
  axios.get(requestUrl).then(response => {
      this.setState({movie: response.data.results})
  });
}

render() {
  //Fires twice. Returns Undefined and an Object
  console.log(this.state.movie[0]);
  return(
   <div></div>
  )
}

2 Answers2

13

Check the state inside the render method. With this approach you can render a loading screen:

import React from "react";
import axios from "axios";

export default class NetflixHero extends React.Component {
 constructor() {
    super();
    this.state = {
      movie: []
    }
 }
}

componentDidMount() {
  const apiKey = '87dfa1c669eea853da609d4968d294be';
  let requestUrl = 'https://api.themoviedb.org/3/' + this.props.apiAction + '&api_key=' + apiKey;
  axios.get(requestUrl).then(response => {
      this.setState({movie: response.data.results})
  });
}

render() {
  //Loading...
  if( this.state.movie[0] === undefined ) {
      return <div>Loading...</div>
  }

  //Loaded successfully...
  return(
   <div> Movie loaded... [Do action here] </div>
  )
}

Explanation

Every time the state changes, a re-render will be triggered. The first time, your Component is constructed with this.state.movie = []. After that, componentDidMount() is triggered, which changes your state. This is triggering the render method a second time.

dschu
  • 4,992
  • 5
  • 31
  • 48
  • 1
    So basicly my application gets rendered before my data is fetched from the source which is why it gets console.logged twice? – Michael Koelewijn Oct 26 '16 at 12:04
  • 1
    Every time the state changes, a re-render will be triggered. The first time, your Component is constructed with this.state.movie = []. After that, componentDidMount() is triggered, which changes your state. This is triggering the render method a second time. – dschu Oct 26 '16 at 12:06
  • 1
    Gotcha! Adding the above code does work. Thanks for clearing that up for me ;-) – Michael Koelewijn Oct 26 '16 at 12:14
  • +1 for this. None of the examples I looked at for multiple react REST service calls mentioned this simple fix for timing issues. – SlackGadget Dec 03 '20 at 12:22
0

Is your post crossdomain?

If your request is a CORS (Cross-origin resource sharing) request it will be preceded with a OPTIONS (pre-flight) request. Have a look at CORS and more specifically to the pre-flighted requests.

Basically the OPTIONS request is used to check if you are allowed to perform the GET/POST request from that domain and what headers can be used for that request. This is not axios specific.

Hasan Sefa Ozalp
  • 6,353
  • 5
  • 34
  • 45