Sorry for any confusion. To put simply I want to make several titles with unordered lists.
<h3>level_3 key title</h3>
<ul>
<li>level_4 value</li>
<li>level_4 value</li>
</ul>
<h3> another level_3 key title</h3>
<ul>
<li>level_4 value</li>
<li>level_4 value</li>
</ul>
Difficult to phrase the problem into a question. Essentially having a really hard time trying to parse through some JSON and display the data correctly. What I would like to do is display level_3.x
below as a top level list item and the nested level_4.x
as nested list items. To be clear using React
Example:
level_3.1
level_4.1
level_4.2
Repeat for every level_3.x
object
Example Data
"level_1":{
"level_2.1":{
"level_3.1":{
"level_4.1":["string","string","string"],
"level_4.2":["string","string","string"]
}
"level_3.2":{
"level_4.1":["string","string","string"],
"level_4.2":["string","string","string"]
}
}
"level_2.2":{
"level_3.1":{
... Same as above
}
"level_3.2":{
... Same as above
}
}
}
What I have done since you can only map an array, from my understanding, is try and go through level_3.x
and push those to an Array. I can map over that and display the items as expected.
Parent Component
render(){
return( <Child heading="A" data={resource.data} /> )
}
Child Component
render(){
let groupObj;
let groupArray;
let subListItems;
if('value' in this.props.data){
var i;
for(i = 0; i < Object.keys(groupObj).length; i++){
groupArray.push(Object.keys(groupObj)[i] + "," + Object.values(groupObj)[i])
// Have removed the Object.values because I was trying to make everything flat and pull out the first item. Leaving it in because that was my original direction in the case it was actually the right way to go
}
}
listItems = groupArray.map((item, index)=>(<li key={index}>{item}</li>));
return({listItems})
}
Thus far I can produce:
level_3.1
level_3.2
console log > [level_3.1,level_3.2]
Which is great, and halfway there. Now where things break down is I can't seem to figure out how to get the level_4.x
elements to render.
I tried writing another map function inside the previous:
listItems = groupArray.map((item, index) => (
<li key={index}>
{item}
<ul>
{subListItems = groupObj.item.map((subItem, index) => (
<li key={index+1}>{subItem}</li>
))};
</ul>
</li>
));
This returns a map of undefined error, however if item
is replaced with a key it'll work. groupObj.level_4.1.map()
That will return a level_4.1
values:
item
from the parent map function will return undefinedSo either doing this completely wrong, or missing a way to pass in a dynamic value into that groupObj.[needs to be dynamic based on parent].map()
Note, do know that using index
as a key value is an anti-pattern just have that in for sake of getting this to work.
Update
Feel like this is 90% there but having one last issue. Took both answers into consideration and the easiest for me to implement and understand what I'm typing at this time is the following:
render(){
let listItems;
let name = this.props.heading
if('level_2' in this.props.data){
let data = this.props.data.level_2[name];
console.log('ok we can get to work', data); // <<< Good
listItems = Object.keys(data).map((propKey) => (
<ul key={propKey}>
{propKey} // <<< Good
{console.log('PROP KEY', propKey)} // <<< Good
{data[propKey].map((childPropKey) =>{
<li key={childPropKey}>
{childPropKey} // <<<<<< PROBLEM, This returns nothing in the DOM
{console.log(childPropKey)} // <<< Good
</li>
})}
</ul>
));
return(<div>{listItems}</div>)
}
So I'm able to console.log(childPropKey)
and return expected results. But just trying to return {childPropKey}
nothing gets returned
Working ES5
listItems = Object.keys(data).map(function(propKey){
return <ul key={propKey}>
{propKey}
{data[propKey].map(function(childPropKey){
return <li key={childPropKey}>
{childPropKey}
</li>
})}
</ul>
});
Working ES6
listItems = Object.keys(data).map((propKey) => (
<ul key={propKey}>
{propKey}
{data[propKey].map((childPropKey) =>(
<li key={childPropKey}>
{childPropKey}
</li>
))}
</ul>
));
Instead of trying to convert the object into an array, just cut that out and loop directly through the Object.keys array.
render () (
<ul>
{Object.keys(this.props.data).map((propKey) => {
<li key={propKey}>
{this.props.data[propKey]}
<ul>
{Object.keys(this.props.data[propKey]).map((childPropKey) => {
<li key={childPropKey}>
{this.props.data[propKey][childPropKey]}
</li>
})}
</ul>
</li>
})}
</ul>
);
I've made some assumptions on your data structure, so hopefully you can translate it to your implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With