Oliver D
Oliver D

Reputation: 2889

How to use ScrollView with nested FlatList?

In Home screen, I have 3 FlatList and some other View's 'other data', So should I wrap it inside ScrollView that enables me to scroll to see other data and so on,

But when I Wrap the FlatList's with scrollView I got this warning

VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.

So how can I solve this issue without making a header/footer component to FlatList?

Demo "Note: I don't get a warning in the expo and I don't use it, that's just an example to see live demo"

here code snippet

const HomeScreen = () => {
  const renderServices = ({item, index}) => {
    return (
      <View style={styles.itemContainer}>
        <View style={styles.serviceImgContainer}>
          <Image
            style={styles.serviceImg}
            source={{
              uri:
                'https://cdn1.iconfinder.com/data/icons/appliance-1/100/dryer-03-512.png',
            }}
          />
        </View>
        <Text>{item.name}</Text>
      </View>
    );
  };
  return (
    <View style={styles.container}>
      <ScrollView style={{flex: 1}}>
        <View style={styles.headerContainer}>
          <Text style={styles.headerText}>
             Booking Now!
          </Text>
          <View style={styles.imgHeaderContainer} />
        </View>
        {/* Services */}
        <View style={styles.servicesContainer}>
          <View style={styles.servicesHeader}>
            <Text style={styles.headerTitle}>Services</Text>
            <TouchableOpacity>
              <Text style={styles.headerTitle}>more</Text>
            </TouchableOpacity>
          </View>
          <FlatList
            scrollEnabled={false}
            data={[
              {id: 0, name: 'service 0', img: 'img.jpg'},
              {id: 1, name: 'service 1', img: 'img.jpg'},
              {id: 2, name: 'service 2', img: 'img.jpg'},
              {id: 3, name: 'service 3', img: 'img.jpg'},
              {id: 4, name: 'service 4', img: 'img.jpg'},
              {id: 5, name: 'service 5', img: 'img.jpg'},
              {id: 6, name: 'service 6', img: 'img.jpg'},
              {id: 7, name: 'service 7', img: 'img.jpg'},
            ]}
            renderItem={renderServices}
            keyExtractor={(item) => item.id.toString()}
            numColumns={4}
            ItemSeparatorComponent={() => <View style={styles.separator} />}
            columnWrapperStyle={styles.columnWrapperStyle}
          />
        </View>

        {/* FlatList Services 2 */}
        <View style={styles.servicesContainer}>
          <View style={styles.servicesHeader}>
            <Text style={styles.headerTitle}>Services</Text>
            <TouchableOpacity>
              <Text style={styles.headerTitle}>more</Text>
            </TouchableOpacity>
          </View>
          <FlatList
            scrollEnabled={false}
            data={[
              {id: 0, name: 'service 0', img: 'img.jpg'},
              {id: 1, name: 'service 1', img: 'img.jpg'},
              {id: 2, name: 'service 2', img: 'img.jpg'},
              {id: 3, name: 'service 3', img: 'img.jpg'},
              {id: 4, name: 'service 4', img: 'img.jpg'},
              {id: 5, name: 'service 5', img: 'img.jpg'},
              {id: 6, name: 'service 6', img: 'img.jpg'},
              {id: 7, name: 'service 7', img: 'img.jpg'},
            ]}
            renderItem={renderServices}
            keyExtractor={(item) => item.id.toString()}
            numColumns={4}
            ItemSeparatorComponent={() => <View style={styles.separator} />}
            columnWrapperStyle={styles.columnWrapperStyle}
          />
        </View>

        {/* FlatList Services 3 .... */} 
            ....
        
        {/* other data */} 
            ....
      </ScrollView>
    </View>
  );
};

Upvotes: 4

Views: 14534

Answers (3)

GSFZamai
GSFZamai

Reputation: 74

Try this: FlatList inside ScrollView doesn't scroll

Basically add the attribute nestedScrollEnabled={true}, in yout external ScrollView and on your internar FlatList. Then set yout FlatList's height to a fixed value. (Worked for my only after setting the height property)

The whole discussion and multiple solutions are on the link above.

Upvotes: 0

olawalejuwonm
olawalejuwonm

Reputation: 1535

Why you will need a scrollview and flatlist is because you want to render somethings before the flatlist or after the flatlist, but there is an inbuilt feature of flatlist that does the same thing and you're not maximizing it, that's why you're getting that warning. They are called List Header Component(which render element before the list without repetition) and List Footer Component (which render element after the list without repetition)

Heres an example:

if (index === 0) {
            return (
                <View>
                <Text>The Team</Text>
                <ListItem
                key={index}
                title={item.name}
                subtitle={item.description}
                hideChevron={true}
                leftAvatar={{source: {uri: baseUrl + item.image}}} 
                />
                </View>
            )
        }
        return (
                <ListItem
                key={index}
                title={item.name}
                subtitle={item.description}
                hideChevron={true}
                leftAvatar={{source: {uri: baseUrl + item.image}}} 
                />
        )
    }

    if (this.props.leaders.isLoading) {
        return (
            <ScrollView>
                <History />
                    <Card title="Corporate Leadership">
                        <Loading />
                    </Card>
            </ScrollView>
        );
    }
    else if (this.props.leaders.errMess) {
        return (
            <ScrollView>
                <Animatable.View animation="fadeInDown" duration={2000} delay={1000}>
                    <History />
                    <Card title="Corporate Leadership">
                        <Text>{this.props.leaders.errMess}</Text>
                    </Card>
                </Animatable.View>
            </ScrollView>
        )

    }
    else {
        return (
                <Animatable.View animation="fadeInDown" duration={2000} delay={1000}>
                        <FlatList
                            ListHeaderComponent={
                                <History />
                            }
                            data={this.props.leaders.leaders}
                            renderItem={renderLeaders}
                            keyExtractor={item => item.id.toString()}
                            // ListFooterComponent={
                            //     <>

                            //     </>
                            // } 
                            />
                </Animatable.View>
        )
    }

}

}

Upvotes: 2

Jon_Mai
Jon_Mai

Reputation: 41

Try to maybe use scrollView inside scrollview instead of flatList? its seems to be automatically enabled for nested scroll when you use scrollView inside scrollView and you can add nestedScrollEnabled too.

Upvotes: 2

Related Questions