ifelsething logoifelsething

SectionList in React Native

Published On: 2024-10-23
Posted By: Harish

basic sectionlist in a react native

Let's think of a scenario where we want a list with grouped items and a header to each group. Like a contact list, where we have a letter as a title and grouped contact names starting with that letter.

In that scenario, we can’t use a general ScrollView component , as ScrollView is best suited for small scrollable content and not for lists.

To avoid those performance issues and to show lists in react native, we have FlatList or VirtualizedList components.

But they are not suitable for our example as they have only one header and footer for the whole list. For our contact list example, we need many headers, in fact many sections with header and footer in a list.

Then in those cases, we can use react native’s SectionList component.

We can divide list data into sections with specific header or footer.

Let's check a basic SectionList using a contact list as an example.

Create A New Project

Create a new react-native project by using npx. Check documentation for creating a new react native project.

npx react-native@latest init SectionListRN

Example Implementation

We will create a simple contact list using the SectionList component.

First import a SectionList component from react-native and add to the view.

//App.tsx
import React from "react";
import { SectionList } from "react-native";
...
<SectionList
  contentContainerStyle={styles.content_container}
/>
...

We have added a basic content style to the sectionlist. You can find more info at contentContainerStyle prop for styling scrollview content post.

Next the main prop to add is sections prop.

Pass the data which needs to be shown in sections.

Unlike FlatList or Virtualized list data format, SectionList component data format is different and fixed.

So, whatever data you have, should be converted to a sectionlist format.

A sectionlist data should be an array list objects with title and data as properties.

...
const data = [
  {
    title: 'A',
    data: [
      'A1 Contact',
      'A2 Contact',
      'A3 Contact'
    ],
  },
  ...
]
...

Here, title key is optional and only add that when you want an individual header or footer to a section. But data is required.

...
<SectionList
  contentContainerStyle={styles.content_container}
  sections={data}
/>
...

Next, add a keyExtractor prop, used by react native for re-rendering purposes.

...
<SectionList
  contentContainerStyle={styles.content_container}
  sections={data}
  keyExtractor={(item, index) => item + index}
/>
...

keyExtractor prop has to be unique.

Next, add a list item view with the help of renderItem callback.

...
<SectionList
  contentContainerStyle={styles.content_container}
  sections={data}
  keyExtractor={(item, index) => item + index}
  renderItem={({ item }) => {
    return (
      <Item item={item} />
    )
  }}
/>
...

This renderItem callback function is similar to react native FlatList prop. For info, check the basic FlatList example too.

Till now, we have implemented a list which are grouped together as sections.

For our example, a contact list, we have an alphabet as a title.

So, add renderSectionHeader function to show a header at the top of each section.

...
<SectionList
  contentContainerStyle={styles.content_container}
  sections={data}
  keyExtractor={(item, index) => item + index}
  renderItem={({ item }) => {
    return (
      <Item item={item} />
    )
  }}
  renderSectionHeader={({section: {title}}) => (
    <Text style={styles.header}>{title}</Text>
  )}
/>
...

If we use the renderSectionFooter function instead of renderSectionHeader, that title appears at the bottom of each section as a footer.

Now, run the app.

#for Android
npx react-native run-android

#for ios
npx react-native run-ios

You will see a list with a title and data related to that title in sections.

So, in this way, we can create a grouped content list in react native app;

grouped list items in a list in react native

Complete code of our example,

//App.tsx
import React from "react";
import {
  Text,
  StyleSheet,
  SafeAreaView,
  StatusBar,
  View,
  SectionList
} from "react-native";

const data = [
  {
    title: 'A',
    data: [
      'A1 Contact',
      'A2 Contact',
      'A3 Contact'
    ],
  },
  {
    title: 'B',
    data: [
      'B1 Contact',
      'B2 Contact',
      'B3 Contact'
    ],
  },
  {
    title: 'C',
    data: [
      'C1 Contact',
      'C2 Contact',
      'C3 Contact'
    ],
  },
  {
    title: 'D',
    data: [
      'D1 Contact',
      'D2 Contact',
      'D3 Contact',
      'D4 Contact'
    ],
  },
];

export default function App() {

  const Item = ({ item }: { item: string }) => {
    return (
      <View
        key={item}
        style={styles.item_view}

      >
        <Text style={styles.item_text}>{item}</Text>
      </View>
    )
  };

  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
      <StatusBar
        barStyle="dark-content"
      />
      <View style={styles.container}>
        <Text style={styles.text}>
          ifelsething.com
        </Text>
        <Text style={styles.text}>
          Basic SectionList
        </Text>
        <SectionList
          contentContainerStyle={styles.content_container}
          sections={data}
          keyExtractor={(item, index) => item + index}
          renderItem={({ item }) => {
            return (
              <Item item={item} />
            )
          }}
          renderSectionHeader={({ section: { title } }) => (
            <Text style={styles.header}>{title}</Text>
          )}
        // renderSectionFooter={({section: {title}}) => (
        //   <Text style={styles.header}>{title}</Text>
        // )}
        />
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    margin: 10,
    gap: 20
  },
  text: {
    fontSize: 15,
    color: 'black',
    fontStyle: 'italic'
  },
  content_container: {
    gap: 10
  },
  item_view: {
    backgroundColor: 'ghostwhite',
    alignItems: 'flex-start',
    justifyContent: 'center',
    padding: 10
  },
  item_text: {
    color: 'black',
    fontSize: 20,
  },
  header: {
    fontSize: 30,
    backgroundColor: 'white',
    color: 'steelblue'
  },
  item_separator: {
    height: 1,
    backgroundColor: 'lightgray'
  }
});

Share is Caring

Related Posts