27
votes

I am using React-Native version 0.43.0 which does not support ListEmptyComponent of FlatList. Hence I am using ListHeaderComponent to render a view when the list is empty,

import React, { Component } from 'react';
import { Text, View, StyleSheet,FlatList } from 'react-native';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      listData: []
    }
  }
  render() {
    return (
      <View style={styles.container}>
        <FlatList
          renderItem={() => null}
          data={this.state.listData}
          ListHeaderComponent={() => (!this.state.listData.length? 
            <Text style={styles.emptyMessageStyle}>The list is empty</Text>  
            : null)
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  emptyMessageStyle: {
    textAlign: 'center',
    //My current hack to center it vertically
    //Which does not work as expected
    marginTop: '50%', 
  }
});

enter image description here

As you can see from the image the text is not centered vertically

Any idea how to center it vertically in a FlatList?

I have already tried applying justifyContent, alignItems etc but no use.

This is a link to the snack.expo - https://snack.expo.io/S16dDifZf

6

6 Answers

43
votes

Hope this will help you

<FlatList
    contentContainerStyle={{ flexGrow: 1 }}
    disableVirtualization={false}
    data={this.state.data}
    renderItem={this.renderItem}
    ListEmptyComponent={this.renderEmptyContainer()}
      />
    }
  />

Place your UI in the renderEmptyContainer() method and boom, Empty container will show up whenever your list is empty

15
votes

They fixed ListEmptyComponent in this pr https://github.com/facebook/react-native/pull/18206. But they will ship in 0.56.

UPDATE: Checkout the official doc ListEmptyComponent

6
votes

You can add a style to the FlatList.

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  listStyle: {
    justifyContent: 'center'
  },
  emptyMessageStyle: {
    textAlign: 'center',
    }

});

  render() {
    return (
      <View style={styles.container}>
        <FlatList style={styles.listStyle}
          renderItem={() => null}
          data={this.state.listData}
          ListHeaderComponent={() => (!this.state.listData.length ? 
            <Text style={styles.emptyMessageStyle}>The list is empty</Text>  
            : null)}
        />
      </View>
    );
  }  

This will center the items in the list, when the list is not empty. You may have to apply another style (when the list is not empty), if you don't prefer the non empty style.

Link to snack.expo

Another option - without changing FlatList style - conditionally rendering FlatList based on this.state.listData.length

render() {
    return (
      <View style={styles.container}>
        {
          this.state.listData.length?

          (<FlatList 
            renderItem={() => null}
            data={this.state.listData}
          />) 
          :
          (
            <View style={styles.emptyListStyle}>
              <Text style={styles.emptyMessageStyle}>The list is empty</Text>  
            </View>
          )
        }
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  emptyListStyle: {
    flex: 1,
    justifyContent: 'center'
  },
  emptyMessageStyle: {
    textAlign: 'center',
    }

});

This is the snack.expo

6
votes

This resolve for me.

<FlatList
    contentContainerStyle={{ flexGrow: 1,
        justifyContent: "center",
        alignItems: "center"}}
    disableVirtualization={false}
    data={this.state.data}
    renderItem={this.renderItem}
    ListEmptyComponent={this.renderEmptyContainer()}
      />
    }
  />
5
votes

You must combine props ListEmptyComponent with contentContainerStyle={{flex:1}} flex:1 will set the maximal height in the container and will allow you to center vertically. ie:

<FlatList 
    ...
    contentContainerStyle={customers.length === 0 && styles.centerEmptySet}
    ListEmptyComponent={<EmptySetCustomer />}
/>

Note that you must set a condition to remove flex:1 when list is not empty. To allow scroller.

Hope it will help.

3
votes

As a temporary workaround you can conditionally set a style to the contentContainer to center only the empty set like this

<FlatList 
    contentContainerStyle={customers.length === 0 && styles.centerEmptySet}
    data={customers}
    renderItem={({ item, index }) => (
        /// Your item here
    )}
    keyExtractor={(item, index) => {
        return String(index);
    }}
    ListEmptyComponent={<EmptySetCustomer />}
/>

And styles like this

centerEmptySet: { justifyContent: 'center', alignItems: 'center', height: '100%' }

Then in 2-3 weeks we can update to 0.56 and remove the workaround