57

I've 4 FlatLists with maxHeight set to 200 inside a ScrollView.

<ScrollView>
  <FlatList/>
  <FlatList/>
  <FlatList/>
  <FlatList/>
</ScrollView>

and when I try to scroll a FlatList, it doesn't scroll but the ScrollView scrolls. How do I fix this issue ?

Full Source Code

import { Component, default as React } from 'react';
import { FlatList, ScrollView, Text } from 'react-native';

export  class LabScreen extends Component<{}> {
  render() {
    return (
      <ScrollView>
        {this.renderFlatList('red')}
        {this.renderFlatList('green')}
        {this.renderFlatList('purple')}
        {this.renderFlatList('pink')}
      </ScrollView>
    );
  }

  getRandomData = () => {
    return new Array(100).fill('').map((item, index) => {
      return { title: 'Title ' + (index + 1) };
    });
  };

  renderFlatList(color: string) {
    return (
      <FlatList
        data={this.getRandomData()}
        backgroundColor={color}
        maxHeight={200}
        marginBottom={50}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({ item }) => <Text>{item.title}</Text>}
      />
    );
  }
}

snack.expo link

theapache64
  • 10,926
  • 9
  • 65
  • 108

10 Answers10

124

We can use the built-in nestedscrollenabled prop for the children FlatList/ScrollView components.

<FlatList nestedScrollEnabled />

This is only required for Android (Nested scrolling is supported by default on iOS).

Aniruddha Shevle
  • 4,602
  • 4
  • 22
  • 36
rnk
  • 2,394
  • 1
  • 19
  • 19
40

I was having a very similar issue until I came across an almost complete solution in a very helpful comment on one of the GitHub issues for the react-native project: https://github.com/facebook/react-native/issues/1966#issuecomment-285130701.

The issue is that the parent component is the only one registering the scroll event. The solution is to contextually decide which component should actually be handling that event based on the location of the press.

You'll need to slightly modify your structure to:

<View>
  <ScrollView>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
  </ScrollView>
</View>;

The only thing I had to change from the GitHub comment was to use this._myScroll.contentOffset instead of this.refs.myList.scrollProperties.offset.

I've modified your fully working example in a way that allows scrolling of the inner FlatLists.

import { Component, default as React } from "react";
import { View, FlatList, ScrollView, Text } from "react-native";

export default class LabScreen extends Component<{}> {
  constructor(props) {
    super(props);
    this.state = { enableScrollViewScroll: true };
  }

  render() {
    return (
      <View
        onStartShouldSetResponderCapture={() => {
          this.setState({ enableScrollViewScroll: true });
        }}
      >
        <ScrollView
          scrollEnabled={this.state.enableScrollViewScroll}
          ref={(myScroll) => (this._myScroll = myScroll)}
        >
          {this.renderFlatList("red")}
          {this.renderFlatList("green")}
          {this.renderFlatList("purple")}
          {this.renderFlatList("pink")}
        </ScrollView>
      </View>
    );
  }

  getRandomData = () => {
    return new Array(100).fill("").map((item, index) => {
      return { title: "Title " + (index + 1) };
    });
  };

  renderFlatList(color: string) {
    return (
      <View
        onStartShouldSetResponderCapture={() => {
          this.setState({ enableScrollViewScroll: false });
          if (
            this._myScroll.contentOffset === 0 &&
            this.state.enableScrollViewScroll === false
          ) {
            this.setState({ enableScrollViewScroll: true });
          }
        }}
      >
        <FlatList
          data={this.getRandomData()}
          backgroundColor={color}
          maxHeight={200}
          marginBottom={50}
          keyExtractor={(item, index) => index.toString()}
          renderItem={({ item }) => <Text>{item.title}</Text>}
        />
      </View>
    );
  }
}

Hopefully you find this useful!

MauriceNino
  • 6,214
  • 1
  • 23
  • 60
Eric Le Fort
  • 2,571
  • 18
  • 24
  • Not a problem! I had to solve the same issue myself so I figured I may as well share the solution. – Eric Le Fort Aug 26 '18 at 21:18
  • What are the values that you use for styling on these elements? – Alex Chin Feb 14 '19 at 19:25
  • @EricLeFort 2 things: 1. The second answer is much better 2. in you code: " this.setState({ enableScrollViewScroll: false }); if (this._myScroll.contentOffset === 0 && this.state.enableScrollViewScroll === false) {" setState is async function and there is no guarantee that line after you get a false value on this.state.enableScrollViewScroll in a matter of fact almost sure it won't be having the false value – Erab BO May 03 '19 at 11:51
  • 1
    this code work well , but when i switch to another view , it doesn't scroll but when i scroll again it scrolls – Mahyar Fard Jul 13 '19 at 07:20
  • Even in 2019, this is the only workaround as far as i know. Tried to use 'nestedscrollenabled' it was not working properly – Tanvir Rahman Nov 17 '19 at 04:42
  • I spent the whole day trying to fix drag-and-drop inside a FlatList, while using the react-native-draggable-flatlist library, where it wasn't dragging since the parent ScrollView would start scrolling. Setting scrollEnabled as soon as the dragging movement begins solved the problem. Thank you. – T. Dayya Nov 18 '19 at 20:53
17

This is the simplest answer that requires zero configuration.. and it works like a charm

<ScrollView horizontal={false}>
    <ScrollView horizontal={true}>
        <Flatlist
          ....
          ....
        />
    </ScrollView>
</ScrollView>
Asmat ullah
  • 681
  • 8
  • 23
i-wizard
  • 226
  • 2
  • 5
15

I fixed my problem with nested FlatList not being able to scroll items on android by simply importing FlatList

import { FlatList } from 'react-native-gesture-handler';

If this would not work, also try to import ScrollView.

import { ScrollView } from 'react-native';
// OR
import { ScrollView } from 'react-native-gesture-handler';

You need to play around with these imports, at least it worked in my case.

phwt
  • 1,356
  • 1
  • 22
  • 42
Vojd Naroda
  • 151
  • 1
  • 5
10

Try to set the FlatList as nested

nestedScrollEnabled={true}

Roberto Clavijo
  • 149
  • 1
  • 6
3

I'm surprised that none of the answers actually worked for me. I went searching for the reason ScrollView and FlatList don't work together and found that there are props on FlatList that can accomodate the header and footer areas above and below my FlatList. If I use this I can make sure the whole screen still scrolls and I don't get the error.

Here is where I found this answer and I've put an example below.

<View>
  <FlatList
    ListHeaderComponent={<View><Text>Top of screen content goes here</Text></View>}
    keyExtractor={(item) => item._id}
    data={[{_id: 1, text: 'one'}, {_id: 2, text: 'two'}]
    renderItem={({item}) => (<View><Text>{item.text}</Text></View>)}
  />
</View>
JoshJoe
  • 1,482
  • 2
  • 17
  • 35
  • This worked for my use case. My goal was to have some content above my flatlist but have that content scroll away when trying to view the flatlist. Nesting a ScrollView and FlatList, at least currently, is giving me lots of problems like firing off way too many refreshes and causing instability – cchoe1 May 17 '23 at 01:24
1

Using View with a flex:1 instead of ScrollView worked for me.

Sunday David
  • 105
  • 5
0

Use map instead of Flatlist, same result and don't break the application

Minha conta
   {
      buttonsProfile.map(button => (
         <ArrowButton 
              key={button.key}
              title={button.title}
              iconName={button.icon} 
              toogle={button.toogle}
              onPress={() => {navigation.navigate(button.route)}}
          />
      ))
    }
                 
Helmons
  • 21
  • 1
0

Make sure you add nestedScrollEnabled to each flatlist / scrollview but most importantly make sure you do not use pos absolute and allow your screen to flex to be able to scroll

Jonathan Coletti
  • 448
  • 4
  • 13
-1

The better answer is to put a horizontal ScrollView inside of the other ScrollView and then the FlatList

Bruno Luiz
  • 64
  • 4