Reputation: 11
I'm new to JSON and filtering. The data.json file and FolderScreen.js below render the following chapter structure in a react native
ListView
. With react-navigation
props are passed down to render the related nested subchapters in the ListView
.
This works flawlessly for Chapter 1
and rendering it's Subchapter A
, B
and C
in the ListView
…
Level 1 > Chapter 1
Subchapter A
Subchapter B
Subchapter C
… but as soon as Subchapter A
is passed down to the FolderScreen.js all its Sub-Subchapters A1
, A2
and A3
are not rendered as expected in the ListView
with the snippet below…
Level 2 > Subchapter A
Sub-Subchapter A1
Sub-Subchapter A2
Sub-Subchapter A3
…am I missing something in the JSON filter?
Or just doing it wrong?
{
"id":"chapter-1",
"name":"Chapter 1",
"type":"folder",
"content":[
{
"id":"sub-chapter-a",
"name":"Subchapter A",
"type":"folder",
"content":[
{
"id":"sub-sub-chapter-a1",
"name":"Sub-Subchapter A1",
"type":"file"
},
{
"id":"sub-sub-chapter-a2",
"name":"Sub-Subchapter A2",
"type":"file"
},
{
"id":"sub-sub-chapter-a3",
"name":"Sub-Subchapter A3",
"type":"file"
}
]
},
{
"id":"sub-chapter-b",
"name":"Subchapter B",
"type":"file"
},
{
"id":"sub-chapter-c",
"name":"Subchapter C",
"type":"file"
}
]
}
renderRow = () => {
const entry = this.props.navigation.getParam('chapterID', '');
const listEntry = jsonData.map(all =>
all.content.filter(parent => parent.id === entry).map(item =>
item.content.map(i => {
return (
<ListEntry
id={i.id}
name={i.name}
type={i.type}
navigation={this.props.navigation}
key={i.id}
/>
);
})
)
);
return listEntry;
};
Upvotes: 1
Views: 1327
Reputation: 1176
Your last map returns an array with only one entry. You need to access the first array item [0] or modify your code to iterate through results.
Here is a simplified version of what works:
const listEntry = jsonData.content
.filter(sub => sub.id === entry)
.map(subsub => subsub.content)[0]
.map(item => {
return <ListEntry id={item.id} name={item.name}/>
}
);
So you should change your code to access the first array member before using the last .map:
const listEntry = jsonData.map(all =>
all.content.filter(parent => parent.id === entry).map(item =>
item.content)[0].map(i => {
return (
<ListEntry
id={i.id}
name={i.name}
type={i.type}
navigation={this.props.navigation}
key={i.id}
/>
);
})
)
);
Here is a working Snack for my sample code: https://snack.expo.io/@navardan/nested-contents
Here is also a good article on .map and .filter Simplify your JavaScript – Use .map(), .reduce(), and .filter()
Upvotes: 0
Reputation: 38121
This is an easy one. Your code expects there to always be a content
property which is an array (or an object that has a .map()
method, anyway).
In the innermost level, there is no "content": []
property.
Either add one, or just add a check in for the content
property before you try to use it.
My favorite technique is to use (item.content || []).map(...
, to use an empty array if the property is null or undefined.
Upvotes: 1