West
West

Reputation: 2570

How to access state values by index in React

I'm struggling to access values inside a state in React using axios and my code is as follows:

import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

class App extends React.Component {
  state = {
    moviedata:null
  }

  getMovies(){
    axios.get("http://127.0.0.1:8000/api/v1/movies/")
      .then(moviedata => {
        this.setState({
          moviedata: moviedata.data    
        });
      })
      .then(x => { console.log(this.state.moviedata)});
  }

  componentDidMount(){
    this.getMovies();
  }

  render () {
    return <h1>Movie Examples include </h1>
  }
}

ReactDOM.render(<App />, document.getElementById('react-app'));

The console.log looks like this:

0: {title: "Terminator 2: Judgement Day", plot: "Rise of the machines.", year: 1991}
1: {title: "The Italian Job", plot: "A comic hinging on a traffic jam", year: 1969}

How can I include the title of the first entry, i.e. 'Terminator 2: Judgement Day', inside the h1 tag, after the word 'include'?

I tried:

render () {
  return <h1>Movie Examples include {this.state.moviedata[0].title}</h1>
}

and got an error TypeError: Cannot read property '0' of null

Upvotes: 1

Views: 2216

Answers (3)

gilamran
gilamran

Reputation: 7294

First, you have to "know" that the component is in a "loading" state. Without that, your state data is undefined (Still loading)

Here's how to do it:

class App extends React.Component {
  state = {
    moviedata:null,
    isLoading: true
  }

  getMovies(){
    axios.get("http://127.0.0.1:8000/api/v1/movies/")
      .then(moviedata => {
        this.setState({
          moviedata: moviedata.data,
          isLoading: false
        });
      })
      .then(x => { console.log(this.state.moviedata)});
  }

  componentDidMount(){
    this.getMovies();
  }

  render () {
    if (this.state.isLoading) {
      return <h1>Please wait...</h1>
    }

    // show only the first movie
    return <h1>Movie #1 {this.state.moviedata[0].title}</h1>;

    // show all the movies
    return (
      <>
        {this.state.moviedata.map((m, idx) => <h1 key={idx}>Movie: {m.title}</h1>}
      </>);
  }
}

Upvotes: 0

kidney
kidney

Reputation: 3083

You have to account for the fact that the Axios request is asynchronous, so the component may render before the data are loaded. For example:

render () {
  const data = this.state.moviedata;
  return <h1>Movie Examples include {data ? data[0].title : ""}</h1>
}

Upvotes: 0

Tholle
Tholle

Reputation: 112777

moviedata in your component state is initially null, so trying to access [0] from that will give rise to your error.

You could e.g. return early from the render method until moviedata has been set.

Example

class App extends React.Component {
  // ...

  render() {
    const { moviedata } = this.state;

    if (moviedata === null) {
      return null;
    }
    return <h1>Movie Examples include {moviedata[0].title}</h1>;
  }
}

Upvotes: 2

Related Questions