简体   繁体   中英

How to filter and render recurring nested JSON data in react native ListView?

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?


data.json

 { "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" } ] }


FolderScreen.js

 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; };


Big thanks for help!

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.

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM