Iterate through nested object in React.js

I’ve asked a similar question here before but I still can’t figure this out.

I have a React project where I’m retrieving JSON data from an API. The API is returning an Object with other Objects nested with in. I am able to programatically iterate through the outer object but I can’t for the life of me figure out how to access the nested object.

For example:

Object1 {
     Object2 {
           propertyIWantToAcess:
           anotherpropertyIWantToAcess:
      }
}

How do I access the properties I want to access? I’m pretty sure it has to involve Object.keys.map but I am unable to figure this out.

This .state.object1.object2.map((item, num) => (
<div key={num}>
<li>Item.name etc</ki>

</div>
)

I tried this and it doesn’t work

Here’s what the data looks like:

An object with other objects nested within it. I want to access the properties within the nested object named content . If I open it it looks like this:

How would I grab the content from each property within this content object i.e. binanceexchange/binance-labs-ask-us-anything, and nairadaddy/good-person-token-something and so on and so forth?

Note that current_route is a property of the outer object and I am able to access this via dot notation i.e. data.current_route

I’ve stored the data within my components state as this.state.myPosts

I can access the elements of the outer object by doing this:

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

    const data = this.state.myPosts;

    const display = Object.keys(data).map((d, key) => {
    return (
      <div className="my-posts">
        <li key={key}>
          {data.current_route}
        </li>
      </div>
      );
    });

    return(
      <div>
        <ul>
          { display }
        </ul>
      </div>
    );
  }

The current_route property I am able to access and properly display because it is not an object. If I try to access content or any of the objects I get an error.

CAn you share the exact code you tried that didn’t work? Could be a simple typo or syntax error. I also have a lot of nested and nested objects and arrays, and I use the method I posted to grab whatever level I need.

do you know the names of these properties ahead of time? (like you know the name of ‘content’ or is that what you’re trying to solve?

Object keys should do that , then you need to use dot notation to get the value from the content.thisKey, which is again another object.

Can you port this to a codepen pen or provide a github link? I understand your question but would hve to play with the syntax to get it working just right.

What I want to do is grab posts from within the content objects. The posts will vary and will always have different names so it’s not something I can just hard code.

And here you go. The code invovled is in the MyPosts component:

In the return function {data.current_route} displays fine because it’s not an object.

If I add {data.content} in the return I get an invalid React object error. Do I need to use Object.keys.map on this?

Dang, that’s some messed up api…or should I say, difficult to work with.

but check this…I ran out of patience but this gets at what you need (check the console), and some simple output

Couldn’t I call Object.keys again on data.content

Something like:

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

    const data = this.state.myPosts;

    const display = Object.keys(data).map((d, key) => {
    return (
      <div className="my-posts">
        <li key={key}>
          {data.current_route}
          
         data.content.Object.keys.map((d, key) => {
              //somehow get around the React object error and display content in here
         });

        </li>
      </div>
      );
    });

    return(
      <div>
        <ul>
          { display }
        </ul>
      </div>
    );
  }

I’ve already done that, but it looks a little different because i pulled out the content when defining the data. I changed the names to make it easier for me to think about the structure and purpose. I think in a case like this, “posts” is much better than “data”, because there are nested and nested levels of “data”.

So yes, you’re right what you’ve done pulls out the name of each post, but you need to dive into each one and pull out it’s content, and that’s what I have done in my sandbox.

Awesome I think that just about covers what I need. Thanks for the help!

1 Like

ouch, it was painful.! Brain hurst…time for bed. Thanks for the challenge.

Well, I haven’t read previous posts. But if accessing all the values in nested object is what you want, try something like this:

const visit = (obj, fn) => {
    const values = Object.values(obj)

    values.forEach(val => 
        val && typeof val === "object" ? visit(val, fn) : fn(val))
}

// Quick test
const print = (val) => console.log(val)

const person = {
    name: {
        first: "John",
        last: "Doe"
    },
    age: 15,
    secret: {
        secret2: {
            secret3: {
                val: "I ate your cookie"
            }
        }
    }
}

visit(person, print)
/* Output
John
Doe
15
I ate your cookie
*/

I’m pretty sure JS util libraries like lodash has better version.

1 Like

Yeah this looks better than my solution.

There has to be a much, much easier way to do this. I am able to console.log the nested object, content, why can’t I just pass the nested object to Object.keys and iterate over it like so:

render() {
    // Logs data
    console.log(this.state.myPosts);

    const data = this.state.myPosts;

    // Stores nested object I want to access in posts variable
    const posts = data.content;

    // Successfully logs nested object I want to access
    console.log(posts);

    // Error, this will not allow me to pass posts variable to Object.keys
    const display = Object.keys(posts).map(key =>
      <option value={key}>{posts[key]}</option>
    )


    return(
      <div>
        {display}
      </div>
    );
 

I get an error TypeError: can't convert undefined to object error when I try to pass posts to Object.keys

The API data is called in a componentDidMount function. Is this what is causing posts to be undefined? The component hasn’t successfully retrieved the posts variable’s data before trying to use it in the render function and this causes it to be undefined?

The behavior of console.log has nothing to do with React. It is illegal to pass an object as a child of a component.
If dumping all the values in a nested object is what you want, then you can convert it to nested array and pass that directly.

Also, you are probably right about why you are getting that error. So, try giving a default state that is fail safe.

What if I set the state to the nested object content to begin with and then use Object.keys to iterate through it? Pretty sure I have the logic down but I can’t figure out the syntax:

import React, { Component } from 'react';
import dsteem from 'dsteem';
import { Client } from 'dsteem';


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

    this.state = {
      myPosts: [],
      nestedObject: []
    }
  }

  componentDidMount() {
    const client = new Client('https://api.steemit.com')

    client.database
      .getState('@ned')
      .then(result => {
        // Old way I've been trying
        this.setState({ myPosts: result });

        // Set nestedObject to the object I want
        this.setState({ nestedObject: result.content});
      })
  }

  render() {
    //console.log(this.state.myPosts);

    //const data = this.state.myPosts;

    //const posts = data.content;
    const posts = this.state.nestedObject;
    //console.log(posts);

    // Somehow use something like this to iterare through nested object
    const display = Object.keys(posts).map(key =>
      <option value={key}>{posts[key]}</option>
    )

    return(
      <div>
        {/*display*/}
    
      </div>
    );
  }



}


export default MyPosts;

Object.keys(o) only returns the outer most keys of an object. So, calling it once will never solve the problem of passing object as a child of a react component.

For example


const person = {
    name: {
        first: "John",
        last: "Doe"
    },
    age: 15,
    secret: {
        secret2: {
            secret3: {
                val: "I ate your cookie"
            }
        }
    }
}

const keys = Object.keys(person) // [name, age, secret]
// person[name] => object, illegal to pass as child
// person[age] => number, can pass as child
// person[secret] => object

So, if the data has 3 levels of nested objects, you need to call Object.keys() at least three times to iterate over all the value.

If you really need to display the whole nested object, then you have to use a function like the one that I’ve wrote in previous post, to convert each primitive data into some React component. And pass that as an array.

For example

let data= []

visit(obj, (val) => {
    data.push(<p>{val}</p>)  // wraps any non-object type inside <p>
})
...
return <SomeComponent> {data} </SomeComponent>

But honestly, I don’t know why you want to iterate over the whole nested object. Why do you need to do this?