Flex React Native FlatList children to grow to full height?

Viewed 3981

I'm using FlatList from React Native to render a bunch of items stacked on top of each other.

This works fine, I've managed to make the FlatList itself expand it's height to fill the available space but I want the FlatList items to grow when there is more space available.

This was simple to do using ScrollView (simplified pseudocode):

<ScrollView
  contentContainerStyle={{
    display: "flex",
    flexGrow: 1,
  }}
>
  <Item key={1} style={{ flexGrow: 1 }} />
  <Item key={2} style={{ flexGrow: 1 }} />
</ScrollView>

However it doesn't work for FlatList (simplified pseudocode):

<FlatList
  contentContainerStyle={{
    display: "flex",
    flexGrow: 1,
  }}
  renderItem={({ index }) => <Item key={index} style={{ flexGrow: 1 }} />}
/>

I've created an Expo Snack showing both the ScrollView successfully growing the elements and the FlatList failing to do so.

There seems to be a lot of discussion online about making the parent FlatList full height, but I've struggled to find anything about making the FlatList items grow to fill the available FlatList height.

I need to use FlatList as I plan to use react-native-draggable-flatlist to implement drag and drop and cannot find an equivalent library that doesn't use FlatList.

A screenshot of the Expo Snack is shown here: Screenshot showing example of ScrollView items growing to fill available height but FlatList items failing to do the same

As seen here, it seems the offending issue in the DOM is the CallRenderer, the VirtualizedList is the right height with the right flex styling, and DayItem is set to grow (and worked fine with ScrollView), but in between there's the CallRenderer which seems to interrupt the flex relationship between the two:

Screenshot inspecting VirtualizedList Screenshot inspecting CallRenderer Screenshot inspecting FlatList child item

Any help is much appreciated.

3 Answers

As a workaround, you can listen to onLayout of the Flatlist, hold the calculated height in a state, and then set each child's height to flatlist height / data.length.

make each item flex: 1 not the flatlist

I found the best method to accomplishing this is to divide the height of the screen or in the case of your example the height of flatlist itself by the number of list items (or the number of items you would like to fill the screen at a time) and set that as the height of renderItem:

 const items = [ { text: "First item" }, { text: "Second item"} ];

 // height given to flatlist
 const FLATLIST_HEIGHT= 200;

 // or number of Items I want to fill screen
 const ITEMS_COUNT = items.length;

 const renderItem = ({ item, index, drag, isActive }) => {
    return (
      <View
        style={{
          borderWidth: 2,
          height: Math.floor(FLATLIST_HEIGHT/ITEMS_COUNT) - 2,
          // minus 2 to compensate for borderWidth
        }}
      >
        <Text>{item.text}</Text>
      </View>
    );
  };

...

 const myFlatList = (
    <FlatList
      data={items}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      contentContainerStyle={{
        height: FLATLIST_HEIGHT,
      }}
    />
  );

In cases where no flatlist fills up the screen simply set the value of the window height:

import {..., Dimensions} from 'react-native';

...
const HEIGHT = Dimensions.get('window').height;

const renderItem = ({ item, index, drag, isActive }) => {
    return (
      <View
        style={{
          borderWidth: 2,
          height: Math.floor(HEIGHT/ITEMS_COUNT) - 2,
          // minus 2 to compensate for borderWidth
        }}
      >
        <Text>{item.text}</Text>
      </View>
    );
  };
Related