Kartikeya Sharma
Kartikeya Sharma

Reputation: 493

React-Native: Flatlist nested in SectionList

I am trying to render a couple of flatlists in a sectionlist. The end goal is this:

A feed page that has multiple sections (Your past orders, It's lunchtime, etc..

However, I can't seem to get it to render properly. It renders the same item multiple times.

            <SafeAreaView style={styles.container}>
                <SectionList
                    sections={posts}
                    keyExtractor={(item, index) => item + index}
                    renderItem={({ item }) => 
                        <FlatList
                            horizontal
                            data={posts}
                            renderItem={this.renderPosts}
                            keyExtractor={(item, index) => index}
                        />
                    }
                    renderSectionHeader={({ section: { title } }) => (
                        <Text style={styles.header}>{title}</Text>
                    )}
                />
            </SafeAreaView>





    renderPosts = (element) => {
        const { image, opinions, votes, name } = element.item;
        return (
            <Card>
                <Card.Cover source={{ uri: image }}/>
                <View>
                    <Card.Content>
                        <Title numberOfLines={1}>{name}</Title>
                    </Card.Content>

                    <Card.Content>
                        <Caption>{opinions} opinions</Caption>

                        <Headline style={{ fontSize: 10 }}>{votes}%</Headline>
                    </Card.Content>
                </View>
            </Card>
        )
    }

The JSON object looks like this:

        const posts = [
            {
                image: 'https://someURL.jpg',
                opinions: 4,
                votes: 87,
                name: 'Yeezy V2 350 Beluga',
                title: 'Recently uploaded',
            },
            {
                image: 'https://someURL.jpg',
                opinions: 12,
                votes: 43,
                name: 'Supreme Hoodie',
                title: 'Popular Streetwear',
            },
            {
                image: 'https://someURL.jpg',
                opinions: 12,
                votes: 90,
                name: 'Travis Scott Air Jordan 1s',
                title: 'Popular Sneakers',
            },
            {
                image: 'https://someURL.jpg',
                opinions: 4,
                votes: 87,
                name: 'Yeezy V2 350 Beluga',
                title: 'Recently uploaded',
            },
            {
                image: 'https://someURL.jpg',
                opinions: 12,
                votes: 43,
                name: 'Supreme Hoodie',
                title: 'Popular Streetwear',
            },
            {
                image: 'https://someURL.jpg',
                opinions: 12,
                votes: 90,
                name: 'Travis Scott Air Jordan 1s',
                title: 'Popular Sneakers',
            }
        ];

and I want to have the sections "Popular Sneakers", "Popular Streetwear", and "Recently Uploaded". The object should render underneath its respective section.

Please help me figure out what I am doing wrong. I know sectionList must have a Data and a Title. But what should I put as data if I want multiple attributes to show for each list.

Upvotes: 5

Views: 13658

Answers (1)

Shivam Tiwari
Shivam Tiwari

Reputation: 626

You can do it without using section list. You can use nested FlatList and pass your data through. By using this approach you can customise or render any layout as section header as well as inside body. You can modify the mentioned codes as per your requirement.

My Dummy JSON data:

var data = [
            {"id": 1,
                "title": "Passed Orders",
                "innerArray": [{
                    "id": 1,
                    "name": "Shivam Tiwari 1",
                    "star": "150",
                    "image": "https://lh3.googleusercontent.com/-sUUgyO92gjw/Xe5Df6MwaZI/AAAAAAAABDc/bYtyIbnUM8ACX83GYB7-XjFzs-HAmbE1QCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 2,
                    "name": "Shivam Tiwari 2",
                    "star": "150",
                    "image": "https://lh3.googleusercontent.com/-OUEDRCj2dQo/Xe5Da2ZmqhI/AAAAAAAABDM/j9qXtid6afYaHNi-pwsOlVOUUdFej-dXgCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 4,
                    "name": "Shivam Tiwari 4",
                    "star": "150",
                    "image": "https://lh3.googleusercontent.com/-ja97CHMzpN4/Xe5DcMVro2I/AAAAAAAABDQ/Z0Tht5w0TIUw37t8newe5YF6RgZYayXFwCK8BGAsYHg/s0/2019-12-09.jpg"
                }]
            },
            {
                "id": 2,
                "title": "Top People",
                "innerArray": [{
                    "id": 5,
                    "name": "Shivam Tiwari",
                    "star": "15000",
                    "image": "https://lh3.googleusercontent.com/-1NXIa1zFf7E/Xe5DyVxnkHI/AAAAAAAABDg/BTB_V4UtLNwQHqIrIXKl6cMKlutU7h3JACK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 6,
                    "name": "Shubham Tripathi",
                    "star": "45",
                    "image": "https://lh3.googleusercontent.com/-ja97CHMzpN4/Xe5DcMVro2I/AAAAAAAABDQ/Z0Tht5w0TIUw37t8newe5YF6RgZYayXFwCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 7,
                    "name": "Kartikeya Sharma",
                    "star": "55",
                    "image": "https://lh3.googleusercontent.com/-sUUgyO92gjw/Xe5Df6MwaZI/AAAAAAAABDc/bYtyIbnUM8ACX83GYB7-XjFzs-HAmbE1QCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 8,
                    "name": "Manoj",
                    "star": "90",
                    "image": "https://lh3.googleusercontent.com/-ulyCVQkAlK4/Xe5DZjhE9dI/AAAAAAAABDI/1zgelciGvyE67cOYEqD-XRlmO-JQAW-yACK8BGAsYHg/s0/2019-12-09.jpg"
                }]
            },
            {
                "id": 3,
                "title": "Favourite Celeb",
                "innerArray": [{
                    "id": 9,
                    "name": "Manoj Kumar Verma",
                    "star": "20",
                    "image": "https://lh3.googleusercontent.com/-OUEDRCj2dQo/Xe5Da2ZmqhI/AAAAAAAABDM/j9qXtid6afYaHNi-pwsOlVOUUdFej-dXgCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 10,
                    "name": "Ashish",
                    "star": "10",
                    "image": "https://lh3.googleusercontent.com/-ulyCVQkAlK4/Xe5DZjhE9dI/AAAAAAAABDI/1zgelciGvyE67cOYEqD-XRlmO-JQAW-yACK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 11,
                    "name": "Balendu Tiwari",
                    "star": "150",
                    "image": "https://lh3.googleusercontent.com/-ja97CHMzpN4/Xe5DcMVro2I/AAAAAAAABDQ/Z0Tht5w0TIUw37t8newe5YF6RgZYayXFwCK8BGAsYHg/s0/2019-12-09.jpg"
                },{
                    "id": 12,
                    "name": "Amit Kumar Singh",
                    "star": "200",
                    "image": "https://lh3.googleusercontent.com/-1NXIa1zFf7E/Xe5DyVxnkHI/AAAAAAAABDg/BTB_V4UtLNwQHqIrIXKl6cMKlutU7h3JACK8BGAsYHg/s0/2019-12-09.jpg"
                }]
            }
        ]

Now you can set it on State:

constructor(props) {
  super(props);

   this.state = {
        dataArr: data
    }; 

}

Here is code for Layout:

<View style={{flex: 1,width: '95%', backgroundColor: '#FFFFFF', alignSelf: 'center'}}>

                        <FlatList data={this.state.dataArr}
                        extraData={this.state}
                        // style={{marginBottom: 200}}
                          renderItem={({ item }) =>
                            <View
                              style={{marginTop: 0, width: '100%', justifyContent: 'center', alignItems: 'center'}} >
                                <View style={{paddingTop: 10,paddingBottom:0, flexDirection: 'column', justifyContent: 'center', alignItems: 'center'}}>
                                    <View style={{backgroundColor: '#000000', paddingHorizontal: 20, borderRadius: 10, elevation: 1, shadowColor: "#0000002B", shadowRadius: 3, shadowOffset: { width: 0, height: 0 }, shadowOpacity: 1.0}}>
                                        <Text style={{fontSize: 30, fontFamily: 'BebasKai', color: '#FFFFFF', textAlign: 'center', paddingHorizontal: 20, paddingVertical: 4}}>{item.title}</Text>
                                    </View>


                                    <FlatList data={item.innerArray}
                                      extraData={this.state}
                                      horizontal={true}
                                      style={{marginTop: 10}}
                                      renderItem={({ item: innerData, index }) =>
                                      <View style={{width: celebViewWidth, height: celebViewHeight, backgroundColor: "#FFFFFF", padding: 5}}>
                                        <TouchableOpacity style={{width: '100%', height: '100%', alignItems: 'center'}}>
                                            <Text style={{fontSize: 15, fontFamily: 'BebasKai', color: '#747474', textAlign: 'center',}} numberOfLines={1}>{innerData.name}</Text>
                                            <View style={{marginTop: 3, flex: 1, width: '100%',  borderRadius: 10, elevation: 1, shadowColor: "#0000002B", shadowRadius: 2, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 1.0, backgroundColor: '#FFFFFF'}}>
                                                <Image 
                                                style={{width: '100%', height: '100%', borderRadius: 10}}
                                                source={{uri: innerData.image}}
                                            />
                                            </View>

                                            <View style={{backgroundColor: 'yellow', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', paddingHorizontal: 5, paddingVertical: 1, borderRadius: 10, position: 'absolute', bottom: 6}}>
                                                <Image 
                                                style={{width: 12, height: 12}}
                                                source={require('../SupportingFiles/Icons/black-star.png')}
                                                />
                                                <Text style={{fontSize: 15, fontFamily: 'BebasKai', color: '#000000', textAlign: 'center', alignSelf: 'center', marginLeft: 3}}>{innerData.star}</Text>
                                            </View>

                                        </TouchableOpacity>
                                      </View>
                                    }/>

                                </View>
                            </View>
                        } />


                   </View>

Please let me know if it fullfil your requirement. Thanks

Upvotes: 6

Related Questions