Problems fetching data from an API

Problems fetching data from an API
0

#1

Hello! I’m trying to fetch an data from an API here is my code.

import React, { Component } from 'react';

class App extends Component {
  constructor(props){
    super(props);

    this.state = {
      items: [],
      isLoaded: false,
      }
    }

    componentDidMount(){

      fetch('https://data.cityofnewyork.us/api/views/25th-nujf/rows.json')
        .then(res => res.json())
        .then(json => {
            this.setState({
              isLoaded: true,
              items: json,
            })
        });
    }

    render() {

      var { isLoaded, items } = this.state;

      if (!isLoaded) {
        return <div>Loading...</div>;
      }

      else {

        return (
          <div className="App">

          <ul>
             {items.map(item => (
                <li key={item.id}>
                      Name: {item.name} | Id: {item.id}
                </li>
             ))};
          </ul>

            </div>
        );

      }
    }
  }
export default App;`

And in the console, I’m getting

TypeError: items.map is not a function

 <div className="App">

<ul>
    {items.map(item => (
     <li key={item.id}>
           Name: {item.name} | Id: {item.id}
       </li>

#2

You think json is an array, but it is actually an object with many nested properties. I suggest loading https://data.cityofnewyork.us/api/views/25th-nujf/rows.json in your web browser, so you can view/study the overall structure.

Which array located in the json response are you wanting to assign to this.state.items?


#3

The goal of this assignment is to pull a set of data, process it and show the results in a visual format. Query a set of data containing the most popular baby names in New York City. Then populate a list of filters: Year, Gender and Ethnicity. Generate a visual representation of the top 10 baby names that match the user’s criteria.


#4

I tried…

import React, { Component } from 'react';
class App extends Component {

  constructor()
   {
    super();
    this.state = {
      data: null,
      }
      this.getData();
    }

    getData()
    {
      let data= fetch('https://data.cityofnewyork.us/api/views/25th-nujf/rows.json').then((resp) =>{
        resp.json().then((res)=>{
        console.log(res.view);
        this.setState({data:res.view})
        })
      })
    }

    render() {

      return (
        <div>
        {
        this.state.data ?
        this.state.data.map((item)=>
        <div>
        <h3>{item.name}</h3>
        </div>
        )
          :
          <h3>Wait... data is fetching</h3>

        }
        </div>


        )
    }
  }

But when I do i get the “Wait…data is fetching” h3 element, but the data doesn’t fetch.


#5

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make easier to read.

See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

Note: Backticks are not single quotes.


#6

There is no property named view in the json returned. The only two property names of json are “data” and “meta”. The data property is an array of arrays with each array having 14 elements. The first element in each element is referred to as the “sid” according to the meta data and the second element is referred to as the “id”. The 3rd to last element contains a name. See below for the first row of the data array:

 [ 30110, "A1A3F29A-FE53-4374-8EEC-AED8B5C3D42D", 30110, 1534519451, "399231", 1534519451, "399231", null, "2011", "FEMALE", "ASIAN AND PACIFIC ISLANDER", "SOPHIA", "119", "1" ]

It appears you can have the same name repeated multiple times, because the data is also segmented by ethnicity. So the same name can appear in the various ethnic groups. I say that to make sure you understand if you try to perform a total on the total number of rows to get a count of unique names, it would be inflated because of duplicates. Also, notice there are some names in all uppercase and some with just a capital first letter, so to get a unique count of names will only be possible if you make them all uppercase or all lowercase.


#7

Once you figure out how to assign the data array to a property in state named data, then you could use the following to display all the names and their corresponding sid number.

      <div className="App">
        <ul>
          {data.map(item => {
            const id = item[0],
                  name = item[item.length - 3];
            return (
              <li key={id}>
                Name: {name} | Id: {id}
              </li>
            );
          })}
        </ul>
      </div>

#8
<p>import React, { Component } from 'react';
class App extends Component {

  constructor()
   {
    super();
    this.state = {
      data: null,
      }
      this.getData();
    }

    getData()
    {
      let data= fetch('https://data.cityofnewyork.us/api/views/25th-nujf/rows.json').then((resp) =>{
        resp.json().then((res)=>{
        console.log(res.meta);
        this.setState({data:res.view})
        })
      })
    }

    render() {

      return (
        <div>
        {
        this.state.data ?
        this.state.data.map((item)=>
        <div>
        <h3>{item.name}</h3>
        </div>
        )
          :
          <h3>Wait... data is fetching</h3>

        }
        </div>


        )
    }
  }



    export default App;</p>

Like this?


#9

Where is setState function?
im no react expert but …
and super() is not that the class above like the class it extends from?
props where is that?


#10

I changed my code from that one. After the one I posted.


#11

You were much closer with the code you originally posted. The fetch should take place in the componentDidMount method. I gave you the code which will produce the unorderd list of names and ids. Your latest code is setting the data property in state to res.view. You should console.log(res.view) before the setState line to see what value res.view has. I think you will be surprised.

As I said before in my previous reply, the JSON response which comes back from the fetch request contains only two properties (data and view). data is an array containing the data you want, so I have no idea why you were assigning res.view to the state property named data.

NOTE:
If you are going to continue to post updates to your code, please use either Codepen, JSFiddle, or CodeSandBo to do so. That way, whoever is helping you can always see the latest code you have tried, instead of you having to post your latest code attempt.


#12

I appericate your help and knownledge Randell. I apologize making it hard to read my code. So this is what I came up with https://codepen.io/devgoi/pen/LJJMvN

Still new to React, literally started this week, so sorry if my questions seem dumb, lol.


#13

When using Codepen, you will need to add the libraries in the JS module for React and ReactDOM and Babel preprocessor using the JS module settings (click the gear). Also, you can not use Import or Export lines like below:

import React, { Component } from 'react';
export default App;

To create a React Component you would write something like:

class App extends React.Component {

}

Once you make the above changes, then you will need to look at your browser’s console to see what kind of errors you have (you have many).

Still not sure why you are not using the fetch in componentDidMount. Make the changes as I have stated in the last couple of replies and let us know when you have made them and fixed most of the errors.


#14

I re-wrote

import React, { Component } from 'react';
export default App;

and changed it to

class App extends React.Component {
}

and also added the fetch inside the componentDidMount. I know this is very basic, but for some reason after a few days working on this, my mind can’t seem to wrap around it. I also copy and added your code. Here’s my update. My Code


#15

Your fetch is missing a .then after it. Also, you reference a resp variable with resp.join(), but you do not define what it is. I strongly suggest you review how to use fetch, because you seem to be misunderstanding the syntax of it and/or Promises.


#16

Ok, after going back to the react docs, and a few videos, here is what I came up with. I did not get any errors, but the code you gave me to show the data in a ul, wouldn’t work. Updated code.


#17

If you look at my 5th reply to you, I said you should not be using the import or the export syntax in Codepen, yet you are still trying to use it. In one of my more recent replies, I said you should go back to what you were first doing with fetch, but it needed to take place in componentDidUpdate. You have it in componentDidUpdate now, but you are trying to use async, but you are not using it correctly either.

I am going to give you pieces of the code and you just need to figure out where they should go.
I am not including some of the functionality you had, but you can review the code you originally posted to insert those things (i.e. like the Loading... part).

class App extends React.Component {
   // put methods in here
}

componentDidMount(){
  fetch('https://data.cityofnewyork.us/api/views/25th-nujf/rows.json')
    .then(res => res.json())
    .then(json => {
      this.setState({
        isLoaded: true,
        items: json,
    })
  });
}  

constructor(props) {
  super(props);
  this.state = { data: [] };
}

One piece I did not include is the ReactDOM.render call. You should search for how to properly make the call, which will depend on what html dom element you plan to target to render the App component.

Also, the React and ReactDOM versions supplied via Codepen are not working properly, so use the following instead:

https://unpkg.com/react@16/umd/react.production.min.js
https://unpkg.com/react-dom@16/umd/react-dom.production.min.js