0

I'm consuming the following dataset from an external source, which contains a 3 level deep array of objects.

const data = [
{name: "Molly", description: [
  {children: [{text: "Likes to run"}] },
  {children: [{text: "Likes ice cream"}]},
  {children: [{text: "Likes to cars"}] }
]},
{name: "Jay", description: [
  {children: [{text: "Likes to race bikes"}]},
  {children: [{text: "Likes cake"}]},
  {children: [{text: "Likes shoes"}]}
]}
] 

I'm wondering if there's an elegant/smarter way to loop over all the array of objects all the way to the text object so I could render its string value.

I'm looking for a vanilla JS solution where I don't end up with several map() functions chained together.

the end result would be to retrieve the text data and render it on a React component such as:

const UserList({ data }) {
  return (
    <div>
      {data.map((user) => (
        <SingleUser user={user} />
      ))}
    </div>
  );
}
 
const SingleUser = ({user}) => {

const userDescription = // loop over and transform to render the text data here
return(
 <>
   <div>{user.name}</div> 
   <div>{userDescription}</div>
 </>
)
}

2
  • Each name have array with three text. Do what's text you like get? First or all ? Commented Dec 15, 2020 at 18:36
  • I'd like to get all of them and render each inside the separate </div> Commented Dec 15, 2020 at 18:39

4 Answers 4

4

You can use flatMap to simplify it a bit, for example

const data = [
{name: "Molly", description: [
  {children: [{text: "Likes to run"}] },
  {children: [{text: "Likes ice cream"}]},
  {children: [{text: "Likes to cars"}] }
]},
{name: "Jay", description: [
  {children: [{text: "Likes to race bikes"}]},
  {children: [{text: "Likes cake"}]},
  {children: [{text: "Likes shoes"}]}
]}
];

const flattenedData = data.map(item => ({
  ...item,
  description: item.description.flatMap(el => el.children[0].text)
}));

console.log(flattenedData);

Sign up to request clarification or add additional context in comments.

2 Comments

this is cool - for my understanding, how come we only pass the first index of children? i.e. el.children[0].text
The second parameter of the map method is the index, so instead of using [0] you can use the [index] there.
4

Use flatMap to simplify a matrix, then use the map in the User component to show the text of the descriptions

const data = [
    {name: "Molly", description: [
      {children: [{text: "Likes to run"}] },
      {children: [{text: "Likes ice cream"}]},
      {children: [{text: "Likes to cars"}] }
    ]},
    {name: "Jay", description: [
      {children: [{text: "Likes to race bikes"}]},
      {children: [{text: "Likes cake"}]},
      {children: [{text: "Likes shoes"}]}
    ]}
    ];
    
    const userData = data.map(item => ({
      ...item,
      description: item.description.flatMap(x => x.children[0].text)
    }));
  
  
  const UserList({ userData }) {
      return (
        <div>
          {userData.map((user) => (
            <SingleUser user={user} />
          ))}
        </div>
      );
    }
     
    const SingleUser = ({user}) => {
    
    const userDescription = // loop over and transform to render the text data here
    return(
     <>
       <div>{user.name}</div> 
   {
     userData.description.map(text => { 
           <div>{text}</div>
     });
   }
     </>
    )
    }

Comments

4

Inspiered in the @Shreevardhan answer but considering every element of the childrens arrays

const data = [
{name: "Molly", description: [
  {children: [{text: "Likes to run"},{text: "To run very fast!"}] },
  {children: [{text: "Likes ice cream"}]},
  {children: [{text: "Likes to cars"}] }
]},
{name: "Jay", description: [
  {children: [{text: "Likes to race bikes"}]},
  {children: [{text: "Likes cake"}]},
  {children: [{text: "Likes shoes"}]}
]}
];

const flattenedData = data.map(item => ({
  ...item,
  description: item.description.flatMap(el => el.children).map(_el => _el.text)
}));

console.log(flattenedData);

3 Comments

this awesome, and covers the ground in case the children receive more than 1 item. How come you had to flatMap twice?
They are applying the second flatMap on the array returned from the first flatMap. Kind of a shorthand to bypass creating an extra variable.
Actually the second one is a regular map, I've corrected it...
2

const data = [
{name: "Molly", description: [
  {children: [{text: "Likes to run"}] },
  {children: [{text: "Likes ice cream"}]},
  {children: [{text: "Likes to cars"}] }
]},
{name: "Jay", description: [
  {children: [{text: "Likes to race bikes"}]},
  {children: [{text: "Likes cake"}]},
  {children: [{text: "Likes shoes"}]}
]}
];

let result = data.reduce( (acc, currentObj) => {
  let obj = {};
  obj.name = currentObj.name;
  obj.description = currentObj.description.reduce( (inneracc, innerObj) =>  inneracc.concat(innerObj.children[0].text), [])
  return acc.concat(obj);
}, [])
console.log(result)

We can achieve this using .reduce() and .concat() methods too. For more info, check out this link Array.prototype.reduce().

Comments

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.