ram
ram

Reputation: 297

Internal data having array of objects could not be rendered

component is getting data in the format given as below

demo.json

{
  "id": "1",
  "name": "john",
  "addr": [
    {
      "addr1": "xyz",
      "addr2": "abc",
      "addr3": "st"
    },
    {
      "addr1": "xyz",
      "addr2": "abc",
      "addr3": "st"
    }
  ]
}

when I try to render the data, I get error TypeError: Cannot read property 'map' of undefined

render() {
  console.log(this.state.itemDetail.addr); // able to see log as [{...},{...}]

  return (
    <div>
      <h1> detail</h1>
      <div>
        <p>{this.state.itemDetail.name}</p> // able to display this
        <div>
        // getting error "TypeError: Cannot read property 'map' of undefined"
            {this.state.itemDetail.addr.map(item => {
              return <p>{item.addr1}</p>;
            })}
          </div>
          // error: TypeError: Cannot read property '0' of undefined
          <p>this.state.itemDetail.addr[0].addr1</P>; 

      </div>
    </div>
  );
}

when data is available inside render(), why internal data array of objects have issue? how to display this?

EDIT:
Providing below, ItemDetail code. after impl modifications suggested, execution doesn't throw errors but doesn't display addr or addr1. data is fetched from local json-server using local demo.json.

ItemDetail.js

import React, { Component } from "react";

export default class ItemDetail extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ItemDetail: {}
    };
  }
  fetchItemDetail() {
    fetch(` http://localhost:4000/items/${this.props.match.params.id}`)
      .then(res => res.json())
      .then(res => {
        this.setState({
          ItemDetail: res
        });
      })
      .catch(console.log);
  }
  componentDidMount() {
    this.fetchItemDetail();
  }
  render() {
    return (
      <div>
        <h1>Item detail</h1>
        <div>
          <p>{this.state.ItemDetail.name}</p>
          <p>{this.state.ItemDetail.destination}</p>
          {Array.isArray(this.state.ItemDetail) &&
            this.state.ItemDetail.addr.map(item => {
              return <p>{item.description}</p>;
            })}
          <p>
            {Array.isArray(this.state.itemDetail) &&
              this.state.ItemDetail.addr.length &&
              this.state.ItemDetail.addr[0].description}
          </p>
        </div>
      </div>
    );
  }
}

Upvotes: 0

Views: 63

Answers (2)

Lakshya Thakur
Lakshya Thakur

Reputation: 8308

Put in a check for this.state.itemDetail to be not equal to undefined and then run the map. It's possible that it's undefined for first render and not for subsequent. I think the following should solve the problem.

{this.state.itemDetail && this.state.itemDetail.addr.length!==0 && this.state.itemDetail.addr.map(item => {
          return <p>{item.addr1}</p>;
        })}

Upvotes: 1

Junius L
Junius L

Reputation: 16122

Don't assume that you'll always get the right data, one of the most important things in programming is validating you data before you use it. Check if the value exists before using it. use Array.isArray to check if the value is array.

render() {
 console.log(this.state.itemDetail.addr); // able to see log as [{...},{...}]

return (
  <div>
    <h1> detail</h1>
    <div>
      <p>{this.state.itemDetail.name}</p> // able to display this
      <div>
        // getting error "TypeError: Cannot read property 'map' of undefined"
        {Array.isArray(this.state.itemDetail.addr) && this.state.itemDetail.addr.map(item => {
          return <p>{item.addr1}</p>;
        })}
        </div>
        // error: TypeError: Cannot read property '0' of undefined
        <p>{Array.isArray(this.state.itemDetail.addr) && this.state.itemDetail.addr.length && this.state.itemDetail.addr[0].addr1}</P>; 

     </div>
   </div>
  );
}

Upvotes: 0

Related Questions