3

This API returns a JSON array of objects, but I'm having trouble with setState and appending. Most documentation covers JSON objects with keys. The error I get from my renderItems() func is: ItemsList.js:76 Uncaught TypeError: Cannot read property 'map' of undefined

in ItemsList.js

import React, { Component } from "react";
import NewSingleItem from './NewSingleItem';
import { findDOMNode } from 'react-dom';

const title_URL = "https://www.healthcare.gov/api/index.json";

class ItemsList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // error: null,
      // isLoaded: false,
      title: [],
      url: [],
      descrip: []
    };
  }

  componentDidMount() {
    fetch(title_URL)
      .then(response => {
        return response.json();
      })
      .then((data) => {
        for (let i = 0; i < data.length; i++) {
          this.setState({
            title: data[i].title,
            url: data[i].url,
            descrip: data[i].bite,
          });
          console.log(data[i])   
        }

      })
      .catch(error => console.log(error));
  }

  renderItems() {
    return this.state.title.map(item => {
      <NewSingleItem key={item.title} item={item.title} />;
    });
  }

  render() {
    return <ul>{this.renderItems()}</ul>;
  }
}

export default ItemsList;

Above, I'm trying to map through the items, but I'm not quite sure why I cant map through the objects I set in setState(). Note: even if in my setState() I use title: data.title, it doesnt work. Can someone explain where I'm erroring out? Thanks.

in App.js

import React, { Component } from "react";
import { hot } from "react-hot-loader";
import "./App.css";
import ItemsList from './ItemsList';

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1> Hello Healthcare </h1>
        <ItemsList />
        <article className="main"></article>
      </div>
    );
  }
}

export default App;

in NewSingleItem.js

import React, { Component } from "react";

const NewSingleItem = ({item}) => {
  <li>
    <p>{item.title}</p>
  </li>
};

export default NewSingleItem;
1
  • I was facing the same issue. Now instead of fetch, I am using axios library to get data from API. While using fetch, the fetched res shows undefined. Commented Apr 2, 2021 at 7:47

1 Answer 1

4

The problem is this line:

this.setState({
  title: data[i].title,
  url: data[i].url,
  descrip: data[i].bite,
});

When you state this.state.title to data[i].title, it's no longer an array. You need to ensure it stays an array. You probably don't want to split them up anyway, just keep them all in a self contained array:

this.state = {
  // error: null,
  // isLoaded: false,
  items: [],
};

...


componentDidMount() {
  fetch(title_URL)
    .then(response => {
      return response.json();
    })
    .then((data) => {
      this.setState({
        items: data.map(item => ({
            title: item.title,
            url: item.url,
            descrip: item.bite,
        })
      });
      console.log(data[i])   
    }
  })

...

renderItems() {
  return this.state.items.map(item => {
    <NewSingleItem key={item.title} item={item.title} />;
  });
}
Sign up to request clarification or add additional context in comments.

5 Comments

Awesome, thanks, noe the states preserved and I have one neat object to handle. The final issue is rendering still isnt working. I've tried passing {...this.state} and {...this.props} to App.js, but the darn list still wont show. Note: the <ul> from render() shows but not the list from renderItems(). any ideas? thanks!
@CatPerry Can you create a reproducible issue on codesandbox.io?
Sure thing: link What I have logging to the console is item object, eventually I'll want to display/manipulate item.title, etc, but for now I'm just trying to the get item.title to render in the NewSingleItem.
@CatPerry Check out my updated sandbox. Few things: 1. Be wary about curly brackets. When you use them in arrow functions param => { ... }, you don't actually return anything. You need to make sure you either include a return statement, or explicitly start your function off with a ( to say "Return everything following this". 2. The data being returned was kinda messed up (It was returning false for the last item from healthcare.gov), so I added a filter to ensure it only showed elements with a title.
It works! Fab. I knew there were a few outstanding issues. I also added a return statement and parens to the NewSingleItem function and that made it work in addition to your fitler() method addition. Thanks for the info about { . . . }. Really appreciate your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.