user11781220
user11781220

Reputation:

How to get the value of a nested object with unknown paths?

Originally, I was rendering components by using this code to map an array of objects( [{}, {}, {}] ):

let todoComponents = allTodos.map(item => <Todos key={item.id} item={item} handleChange={handleChange}/>)

enter image description here

However, this does not work on a separate project where I am getting data from Firebase with a different data structure. In it, each object has a unique name.

[{
  "-M8CpcbvDriZpw4sc4IW" : {
    "completed" : false,
    "id" : "-M8CpcbvDriZpw4sc4IW",
    "text" : "Get Comic Book"
  },
  "-M8Cpku0PCNu0_Eajtuu" : {
    "completed" : false,
    "id" : "-M8Cpku0PCNu0_Eajtuu",
    "text" : "Take out Trash"
  }
}]

The problem is that .map doesn't know where to look for the value of item. In the first example, .map looked for an array -> object(with values). This doesn't work for the data from firebase because array -> object -> object(with values). How can I tell .map to skip over the extra object without know the exact path in the nested object?

Upvotes: 1

Views: 1058

Answers (4)

3limin4t0r
3limin4t0r

Reputation: 21150

If the intent is to convert:

[{
  "-M8CpcbvDriZpw4sc4IW" : {
    "completed" : false,
    "id" : "-M8CpcbvDriZpw4sc4IW",
    "text" : "Get Comic Book"
  },
  "-M8Cpku0PCNu0_Eajtuu" : {
    "completed" : false,
    "id" : "-M8Cpku0PCNu0_Eajtuu",
    "text" : "Take out Trash"
  }
}]

To:

[{
  "completed" : false,
  "id" : "-M8CpcbvDriZpw4sc4IW",
  "text" : "Get Comic Book"
}, {
  "completed" : false,
  "id" : "-M8Cpku0PCNu0_Eajtuu",
  "text" : "Take out Trash"
}]

You can do so with a combination of flatMap and Object.values():

allTodos = allTodos.flatMap(todos => Object.values(todos));

Or if allTodos always contains a single object with todos you could do:

allTodos = Object.values(allTodos[0]);

After converting the data structure you can then execute your statement:

let todoComponents = allTodos.map(item => <Todos key={item.id} item={item} handleChange={handleChange}/>)

Upvotes: 1

Shijil Narayanan
Shijil Narayanan

Reputation: 1019

Try this

const data = [{
  "-M8CpcbvDriZpw4sc4IW": {
    "completed": false,
    "id": "-M8CpcbvDriZpw4sc4IW",
    "text": "Get Comic Book"
  },
  "-M8Cpku0PCNu0_Eajtuu": {
    "completed": false,
    "id": "-M8Cpku0PCNu0_Eajtuu",
    "text": "Take out Trash"
  }
}];

const todoList = [];
Object.keys(data[0]).forEach( key => todoList.push(data[0][key]));
console.log(todoList)

Upvotes: 0

J&#225;n Jakub Naništa
J&#225;n Jakub Naništa

Reputation: 1926

If you call the object that you got from firebase let's say data then:

const obj = data[0]; // i am assuming there is only one object in the array
const allTodos = Object.values(obj); // allTodos is now an array of todos and you can use your original code

Upvotes: 1

Soham
Soham

Reputation: 725

If it helps!

let data = [{
  "-M8CpcbvDriZpw4sc4IW": {
    "completed": false,
    "id": "-M8CpcbvDriZpw4sc4IW",
    "text": "Get Comic Book"
  },
  "-M8Cpku0PCNu0_Eajtuu": {
    "completed": false,
    "id": "-M8Cpku0PCNu0_Eajtuu",
    "text": "Take out Trash"
  }
}]

data.map(ele => {
   let keys = Object.keys(ele);
   
   keys.forEach(key => {
    console.log("item is", ele[key])
   })
});

Upvotes: 0

Related Questions