Error while indexing data from this.setState()

160 Views Asked by At

I am creating a GIF search web app with the GIPHY API and react.

After I fetch the data from the API, I can index the data console.log(json.data[0])

.then((json) => {
      console.log(json.data[0]);
      this.setState({ myGif: json });
});

But when I set my state to the JSON file and I try to index the data console.log(this.state.myGif.data[0]) I get an error

TypeError: Cannot read property “0” from undefined

    render() {
        console.log(this.state.myGif.data[0]);
        return (
            <div>
                <h1>This is </h1>
            </div>
        );
    }

I would really appreciate getting a response

Below is the full code of the component

import React, { Component } from 'react';

export class Content extends Component {
    constructor(props) {
        super(props);

        this.state = {
            myGif: {},
        };
    }

    componentDidMount() {
        const api_key = 'rYJ5AxF8DXFqeX8ub81fbuje3J12lrh6';
        fetch(
            `http://api.giphy.com/v1/gifs/search?q=ryan+gosling&api_key=${api_key}&limit=3`
        )
            .then((response) => response.json())
            .then((json) => {
                console.log(json.data[0]);
                this.setState({ myGif: json });     
            });
    }

    render() {
        console.log(this.state.myGif.data[0]);
        return (
            <div>
                <h1>This is </h1>
            </div>
        );
    }
}

export default Content;
5

There are 5 best solutions below

1
On BEST ANSWER

Try to console.log data like:

console.log(
      this.state.myGif.data
        ? this.state.myGif.data[0]
        : "data is not downloaded yet"
    );
0
On

Your fetch and setState calls are both asynchronous. While it is fetching your render will already be called.

One way to fix this is to check for the current state e.g.

 render() {
        this.state.myGif && console.log(this.state.myGif.data[0]);
        return (
            <div>
                <h1>This is </h1>
            </div>
        );
    }
1
On

It's because when the first time the component is rendered, this.state.myGif.data does not exist, because the initial state of the myGif is just empty. You should check if the data is loaded ...

console.log(this.state.myGif.data ? this.state.myGif.data[0] : "Loading •••");
0
On

import React, { Component } from 'react';

export class Content extends Component {
    constructor(props) {
        super(props);

        this.state = {
            myGif: {data:["Image is getting Loaded"]},
        };
    }

    componentDidMount() {
        const api_key = 'rYJ5AxF8DXFqeX8ub81fbuje3J12lrh6';
        fetch(
            `http://api.giphy.com/v1/gifs/search?q=ryan+gosling&api_key=${api_key}&limit=3`
        )
            .then((response) => response.json())
            .then((json) => {
                console.log(json.data[0]);
                this.setState({ myGif: json });     
            });
    }

    render() {
        console.log(this.state.myGif.data[0]);
        return (
            <div>
                <h1>This is </h1>
            </div>
        );
    }
}

export default Content;

0
On

You don't need json().

componentDidMount() {
        const api_key = 'rYJ5AxF8DXFqeX8ub81fbuje3J12lrh6';
        fetch(
            `http://api.giphy.com/v1/gifs/search?q=ryan+gosling&api_key=${api_key}&limit=3`
        )
            .then(response => {
                const data = response.data
                this.setState(data);     
            });
    }

Then in your render function you can console.log(this.state) to see your entire state. It's an array of objects so you'll need to map it out if you want to display all of them. You can map like this :

this.state.data.map((item,i) => <li key={i}>Test</li>)

Since data in your state may be undefined on the first render. You'll want to set a default value of [] for this.state.data

If you want to display the first one you can say this.state && this.state[0].type