Search code examples
react-nativereact-native-flatlist

React Native: FlatList is not showing


I am trying to make a custom component that will display options for a new choice if the first choice is not clear enough. I am using the FlatList component to display the data and it seems to not be displaying the data that is given as a prop.

This is the render function for the component

import { Header, List, ListItem } from "react-native-elements";
import PickerBox from "./PickerBox";

render() {
    return (
      <View>
        <Header
          centerComponent={{
            text: "By " + this.state.newTaxon + ", did you mean...",
            style: { color: "white", fontSize: 20, textAlign: "center" }
          }}
          backgroundColor="black"
        />
        <FlatList
          data = {this.state.dataSource}
          renderItem = {({item}) => {
            <PickerBox
              title = {item.c_syn_name}
            />
          }}
          keyExtractor = {(item) => item.c_syn_name}
        />
      </View>
    );
}

This is the PickerBox component

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "row",
    padding: 10,
    marginLeft: 16,
    marginRight: 16,
    marginTop: 8,
    marginBottom: 8,
    borderRadius: 5,
    backgroundColor: "#FFF",
    elevation: 2
  },
  title: {
    fontSize: 16,
    color: "#000"
  },
  container_text: {
    flex: 1,
    flexDirection: "column",
    marginLeft: 12,
    justifyContent: "center"
  },
  description: {
    fontSize: 11,
    fontStyle: "italic"
  }
});

const PickerBox = (title) => {
  return (
    <View style={styles.container}>
        <Text style={styles.container_text}>{title}</Text>
    </View>
  );
};

export default PickerBox;

This is the import statement for the PickerBox in the component

import PickerBox from "./PickerBox"; // reside in same folder

The dataSource state comes from a JSON object that contains a layout like this in each entry.

"c_node_name_scientific": "Centurio",
"c_syn_name": "wrinkle-faced bat",
"i_node_id": 27644,

The Output in the simulator is just the header, but the expected output is the header with the list underneath.


Solution

  • Firstly, You need to make sure that if your renderItem method uses a fat arrow function with curly braces like you are in your example, you need to add a return statement like so:

    renderItem={({item}) => { return <PickerBox title={item.c_syn_name} /> }}
    

    If you don't use curly braces you can define the function like this:

    renderItem={({item}) => <PickerBox title={item.c_syn_name} />}
    

    Secondly, make sure that the data is an array, not an object. As per the description of the FlatList's data prop in the react-native documentation:

    For simplicity, data is just a plain array. If you want to use something else, like an immutable list, use the underlying VirtualizedList directly.

    From your question it seems as if you're wanting to loop through an array of objects similar to this:

    [
      {
        "c_node_name_scientific": "Centurio",
        "c_syn_name": "wrinkle-faced bat",
        "i_node_id": 27644
      },
      {
        "c_node_name_scientific": "xxx",
        "c_syn_name": "xxx",
        "i_node_id": 123
      },
      //...
    ]
    

    If this is the case, just wrap the state's dataSource object in an array as demonstrated above.

    If you're wanting to pass in the data as an object similar to this:

    {
      key1: {title: 'Title 1'},
      key2: {title: 'Title 2'}
      key3: {title: 'Title 3'}
    }
    

    you would need to do something like the following to make the data accessible to the FlatList:

    <FlatList
      data={Object.keys(this.state.dataSource)}  // will result in ["key1", "key2", "key3"]
      renderItem={({item}) => 
        // here `item` will be the Object's key. eg: "key1"
        <PickerBox title={this.state.dataSource[item].title} />
      }
    />
    

    And finally, if the Flatlist needs to update as State updates, you need to add in the prop extraData={this.state} to the FlatList. As per the FlatList Documentation:

    By passing extraData={this.state} to FlatList we make sure FlatList itself will re-render when the state.selected changes. Without setting this prop, FlatList would not know it needs to re-render any items because it is also a PureComponent and the prop comparison will not show any changes.