Bhavan Kris Bhavan Kris -4 years ago 65
JSON Question

displaying nested JSON with react js

i have object something like this

export const contact =
{
_id: "1",
first:"John",
name: {
first:"John",
last:"Doe"
},
phone:"555",
email:"john@gmail.com"
};


i am reading it like

return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact._id}</h1>
</div>
)


in this scenario i am getting expected output.

return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact.name.first}</h1>
</div>)


when i read the nested property i am getting error like Uncaught TypeError: Cannot read property 'first' of undefined

how to read these king of nested objects in react

https://github.com/bhavankris/testing1/blob/master/src/pages/contact-list-page.js

please find the github repo

Answer Source

Three things you need to address here:
1. this is your contacts-data and i don't see any first property within the name object:

export const contacts = 
  {"name": "mkyong",
    "age": 30,
    "address": {
        "streetAddress": "88 8nd Street",
        "city": "New York"
    },
    "phoneNumber": [
        {
            "type": "home",
            "number": "111 111-1111"
        },
        {
            "type": "fax",
            "number": "222 222-2222"
        }
    ]
};

2. You are calling this.props.fetchContacts(); on componentDidMount, hence in the first render call the state is still empty, the action call and the reducer will pass new props or change the state then you get to the second render call and that's the moment you have the data ready for use.
So you should check for the existing of the data before you try to use it. one way is to just conditionally render it (of course there are better ways to do it, this is just to make a point):

  render() {
    const { contacts } = this.props;
    return (
      <div>
        <h1>List of Contacts</h1>
        <h2>{contacts && contacts.name && contacts.name.first
          //still getting error. "this.props.contacts.name" alone works
          }</h2>
        <h2>{contacts && contacts.address && contacts.address.city}</h2>
      </div>
    )
  } 
  1. You are trying to use this.props.contact.name.first is that a typo? shouldnt it be contacts instead of contact?

EDIT: As a followup for your comment, as a general rule in JavaScript (or any other language for that manner) you should always check the existence reference of an object before you are trying to access it's properties.
As for your use case you can use defaultProps if you must have a value to render or you can even simplify the scheme of your data.
This is much simpler to manage:

export const contacts =
    {
        "fName": "mkyong",
        "lName": "lasty",
        "age": 30,
        "streetAddress": "88 8nd Street",
        "city": "New York",
        "homeNumber": "111 111-1111",
        "faxNumber": "222 222-2222"
    };

Than this:

export const contacts = 
  {"name": "mkyong",
    "age": 30,
    "address": {
        "streetAddress": "88 8nd Street",
        "city": "New York"
    },
    "phoneNumber": [
        {
            "type": "home",
            "number": "111 111-1111"
        },
        {
            "type": "fax",
            "number": "222 222-2222"
        }
    ]
};
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download