Cosmos
Cosmos

Reputation: 121

React .map returns undefined with Fetch API

I want my React render method to return objects from an API in a similar way to what I get from Postman. For example:

{
  "meta": {
    "count": 807,
    "countReturned": 10,
    "requestTime": 1552524395,
    "responseTime": 1552524395,
    "responseMs": 7
  },
  "data": [
     {
        "type": "breeds",
        "id": "1",
        "attributes": {
            "name": "Abyssinian"
        },
        "relationships": {
            "species": {
                "data": [
                    {
                        "type": "species",
                        "id": "3"
                    }
                ]
            }
        },
        "meta": []
    },

But I'm having trouble using .map to produce the object(s) I want. Here is my code:

class Results extends Component {
constructor() {
    super();
    this.state = {
        animals: [],
    };
}

componentDidMount() {
    var url = "https://test1-api.rescuegroups.org/v5/public/animals/breeds?fields[breeds]=name&fields[species]=singular,plural,youngSingular,youngPlural&include=species&options=meta&limit=10";
    const API_KEY = process.env.REACT_APP_API_KEY;

    fetch(url, {
        method: 'GET',
        headers: {
            Authorization: API_KEY,
            'Content-Type': 'application/json'}
    })
    .then(response => response.json())
    .then(data => this.setState({animals: data.results }))
}

render() {
    return (

        <div>
            {this.state.animals.map(animal => <div>{animal.results}</div>)}
        </div>

    )
}
}

export default Results;

Any tips are appreciated!

Upvotes: 0

Views: 1378

Answers (3)

tam.dangc
tam.dangc

Reputation: 2032

The parameter of the callback method named 'data' doesn't mean it's a data property of the response data.

I think the callback should be

...
.then(response => response.json())
.then(response => this.setState({animals: response.data}))

<div>
  {this.state.animals.map(animal => <div>{animal.type}</div>)}
</div>

Upvotes: 1

Gregory Friedman
Gregory Friedman

Reputation: 76

I think this is confusing you because of a slightly confusing naming convention you have. Your componentDidMount function will need to look as follows:

componentDidMount() {
    var url = "https://test1-api.rescuegroups.org/v5/public/animals/breeds?fields[breeds]=name&fields[species]=singular,plural,youngSingular,youngPlural&include=species&options=meta&limit=10";
    const API_KEY = process.env.REACT_APP_API_KEY;

    fetch(url, {
        method: 'GET',
        headers: {
            Authorization: API_KEY,
            'Content-Type': 'application/json'}
    })
    .then(response => response.json())
    .then(json => this.setState({animals: json.data }))
}

You need to pull the data key out of the response, which, with your current naming, would be data.data.

In your render function, you will then use the animals from your state. If you wanted the name of the animal, you would use the following:

render() {
    console.log(this.state);
    return (

        <div>
            {this.state.animals.map(animal => <div>{animal.attributes.name}</div>)}
        </div>

    )
}

Upvotes: 1

Parth Patel
Parth Patel

Reputation: 3997

If you are sure that the JSON data you are getting is correct, then you can loop over the object using the following code.

 Object.keys(this.state.animals).map((key) => {
    return <div value={key}>{ this.state.animals[key] }</div>
});

Upvotes: 1

Related Questions