DEV Community

Swarnali Roy
Swarnali Roy

Posted on

Nested ScrollViews can be Tricky in React Native! How to solve?

Working with multiple components that use Scrollview or Flatlist in a single screen is a common practice in React Native. Often the nested scrolling behaviour doesn't work properly and can be tricky to use efficiently. I have struggled with this several times so thought to share the easy solution I found for this.

Let's talk a bit about Scrollview and Flatlist at first!

ScrollView or Flatlist, which one to use?

Typically, we use ScrollView to make a screen scrollable in React Native.

  • This component allows the content to scroll vertically or horizontally when it exceeds the screen size. If the content inside the ScrollView doesn't exceed the screen size, no scrolling may occur.
  • Needs to have a bounded height in order to work properly, all parents elements also need to get a bounded height. Failing to do so might occur errors and lead to not achieving the desired scrolling behaviour.
  • ScrollView renders all its react child components at once.
  • For displaying a very long list of contents, it may cause slow rendering and increased memory usage.

To achieve a more efficient rendering when dealing with long lists of data, using Flatlist is definitely a better choice!

  • FlatList renders only the items that are currently visible on the screen and a few items before and after for smooth scrolling.
  • Uses lazy loading and removes items that scroll way off screen to save memory and processing time.
  • It offers various customization options such as custom item separators, headers, footers, and more, allowing user to create a tailored list experience.

I am not going into much details about the usage of these two here as you can get well documented examples in the official React Native Documentation [https://reactnative.dev/]

If your screen has only one component that needs to be scrollable, it's easier to choose depending on your project requirements. But the problem occurs, when you have to use multiple components in a single screen and more than one component needs to be scrollable!

It is recommended to avoid nesting multiple ScrollViews in a single screen.

Reasons to avoid Nested ScrollViews

  1. When user use one Scrollview inside another, the parent and child ScrollViews can compete for touch events, thus leads to unpredictable scrolling behaviour.
  2. The inner ScrollView might not scroll properly or might interfere with the outer ScrollView's scrolling.
  3. The scrolling behaviour may vary across different devices and platforms (iOS vs Android).
  4. Performance can be degraded if the data or list is huge and the layout is complex.
  5. UI design might break, such as the height might not be adjusted as desired.

How to Solve This!

Using a FlatList instead of a ScrollView for the inner scrollable component is a great way to solve this issue, especially when dealing with long lists of data. FlatList is optimized for performance and provides features like pull-to-refresh and infinite scrolling.

In my app, I needed the whole screen to be scrollable, so I used ScrollView as the parent component. Inside that, I had to render a playlist which was a long list so I used a Flatlist to render that in this way:

// Sample data for the FlatList
  const data = Array.from({length: 50}, (_, index) => ({
    id: String(index),
    title: `Item ${index + 1}`
  }));

  const renderItem = ({ item }) => (
    <View style={styles.item}>
      <Text>{item.title}</Text>
    </View>
  );

return (
    <ScrollView style={styles.mainContainer}>
      <Text>Main Content</Text>
      {/* Some content here */}

      <View style={styles.contentSection}>
        <Text>This is part of the main scrollable area</Text>
      </View>

      {/* Separately scrollable FlatList */}
      <View style={styles.separateScrollContainer}>
        <FlatList
          data={data}
          renderItem={renderItem}
          keyExtractor={item => item.id}
          nestedScrollEnabled={true}
        />
      </View>
      <View style={styles.contentSection}>
        <Text>More content in the main scrollable area</Text>
      </View>
    </ScrollView>
  );

const styles = StyleSheet.create({
  mainContainer: {
    flex: 1,
  },

  separateScrollContainer: {
    height: 200, // Set a fixed height for the separate scrollable area
    borderWidth: 1,
    borderColor: 'gray',
    margin: 16,
  },
});



Enter fullscreen mode Exit fullscreen mode

At first the Flatlist scroll was not working properly and the height for the inner component was not adjusted, even though I used flex: 1 for the main container .
To make sure it works perfectly the main things that I had to do was:

  • Using nestedScrollEnabled={true} on the FlatList
  • Keeping the FlatList inside a View with a fixed height, as shown in the separateScrollContainer style.

In this way, the FlatList automatically handles its own scrolling within the confined space.

Some Additional Tips

  • FlatList props like initialNumToRender, maxToRenderPerBatch, and windowSize can be used to optimize performance, especially if you're rendering a larger list.
  • If the FlatList content is shorter than its container, unwanted bouncing effects might occur. To prevent this situation, bounces={false} can be added to the FlatList props.
  • If user wants the FlatList to take up all remaining space, using flexbox instead of a fixed height for the wrapper View of the FlatList Component might be a better choice.

I hope this helps solving nested ScrollView issues for people who are struggling building up some great quality React Native applications!

Happy Coding!

Top comments (0)