skip to content

In a React Native SectionList, how does SectionSeparatorComponent differ from ItemSeparatorComponent, and which props do separators receive?

level: middleimportance: nice to knowfreq 15%

answer

  1. item separators stay inside a section
  2. section separators bracket the items
  3. leading and trailing item and section
  4. components get props, elements do not
  5. empty sections get no separators

basics

~20 s

In a React Native SectionList, ItemSeparatorComponent renders between items within a section only, while SectionSeparatorComponent renders before a section's first item and after its last. Both receive highlighted, section and leading/trailing item and section props when passed as components.

solid answer

~50 s

`ItemSeparatorComponent` renders **between items of the same section** — never after a section's last item. `SectionSeparatorComponent` renders at the **top and bottom of each section's items**: between the header and the first item, and between the last item and the footer, which lets you style the gap around a group differently from the lines inside it. Both are rendered inside the item cells, so a section with no items gets no separators. When you pass a component (not an element), it receives `highlighted`, `section`, `leadingItem`, `trailingItem`, `leadingSection` and `trailingSection`, plus anything set through `separators.updateProps`; `separators.highlight()` in `renderItem` toggles `highlighted` on the separators around that row. A section can override `ItemSeparatorComponent` on its own section object. In a music library, thin inset lines between artists and a full-width rule around each letter group is the typical split.

code

tsx · 36 lines
tsx
import {SectionList, StyleSheet, Text, View} from 'react-native';

type Artist = {id: string; name: string};
type LetterSection = {key: string; title: string; data: Artist[]};

// Component form: receives highlighted, section, leading/trailing props.
function ArtistLine({highlighted}: {highlighted?: boolean}) {
  return <View style={[styles.line, highlighted && styles.hidden]} />;
}

function GroupGap() {
  return <View style={styles.gap} />;
}

export function ArtistList({sections}: {sections: LetterSection[]}) {
  return (
    <SectionList
      sections={sections}
      keyExtractor={a => a.id}
      ItemSeparatorComponent={ArtistLine} // between artists of one letter
      SectionSeparatorComponent={GroupGap} // before first and after last artist
      renderSectionHeader={({section}) => (
        <Text style={styles.header}>{section.title}</Text>
      )}
      renderItem={({item}) => <Text style={styles.row}>{item.name}</Text>}
    />
  );
}

const styles = StyleSheet.create({
  line: {height: StyleSheet.hairlineWidth, marginLeft: 12, backgroundColor: '#d4d4d8'},
  hidden: {opacity: 0},
  gap: {height: 8},
  header: {backgroundColor: '#ffffff', paddingHorizontal: 12, fontWeight: '700'},
  row: {paddingHorizontal: 12, paddingVertical: 10},
});

go deeper

for a junior

Recall the split: item separators between rows of one section, section separators before the first and after the last row of each section.

for a middle

Explain the props separators receive, including leading and trailing items and sections, and why only the component form gets them. Know that highlight toggles the separators around a row.

for a senior

Predict the rendered lines for edge cases: empty sections, the gap before the next header, per-section item separator overrides, and separator height inside measured cells.

for a principal

Keep grouped-list styling in one shared set of separator components so every grouped screen draws group boundaries the same way.

## Two separators, two jobs A `FlatList` has one separator slot. A `SectionList` has two, because grouped lists usually need two kinds of lines: | Prop | Where it renders | Typical look | |---|---|---| | `ItemSeparatorComponent` | between adjacent items **of the same section** | a thin line, inset from the left | | `SectionSeparatorComponent` | before a section's first item and after its last item | a full-width rule or extra spacing | The docs describe `SectionSeparatorComponent` as "rendered at the top and bottom of each section", adding that this is different from `ItemSeparatorComponent`, "which is only rendered between items". In the implementation: - the first item of each section renders the section separator **before** itself (between the section header and that item); - the last item of each section renders the section separator **after** itself, and no item separator; - every other item renders the item separator after itself. ## Consequences of rendering inside item cells Separators are drawn as part of the item cells, not as cells of their own. That has practical effects: 1. **An empty section has no separators**, because it has no item cells; its header and footer render back to back. 2. **Without a section separator, there is no line between the last item of one section and the next header**, because the item separator is suppressed after a section's last item. 3. Separator height is part of the item cell's measured size, which matters if you compute item layouts yourself. ## The props separators receive When you pass a **component** (for example `SectionSeparatorComponent={LetterRule}`), React Native renders it with: - **`highlighted`** — toggled by `separators.highlight()` and `separators.unhighlight()` from `renderItem`, which update the separators around that row, for example to hide lines while a row is pressed; - **`section`** — the section the separator belongs to; - **`leadingItem`** and **`trailingItem`** — the items above and below it, when there are any; - **`leadingSection`** and **`trailingSection`** — the neighbouring sections; - any props you set with `separators.updateProps('leading' | 'trailing', newProps)`. When you pass an **element** (for example `ItemSeparatorComponent={<View style={styles.line} />}`), the element is rendered as-is, and none of these props reach it. Use the component form whenever a separator must react to highlighting or to its neighbours. ## Per-section overrides A section object may carry its own `ItemSeparatorComponent`, which replaces the list-level one inside that section. A music library could use a thicker line between items in a "Favourites" section and the standard inset line elsewhere. `SectionSeparatorComponent` is list-level only. ## Building the music library look For an A-Z artist list: - `ItemSeparatorComponent`: a hairline inset to line up with the artist name; - `SectionSeparatorComponent`: a small vertical gap, so each letter group reads as a block; - `renderSectionHeader`: the letter, with an opaque background if headers stick. ## Common mistakes - Expecting `ItemSeparatorComponent` to draw a line under the last artist before the next letter. - Passing separators as elements and wondering why `highlighted` never changes. - Leaving empty sections in the data and getting a header with no separators or rows. - Adding borders to every row as well as separators, doubling the lines.

  • Why is there no line between the last artist under A and the B header?
    `ItemSeparatorComponent` is suppressed after the last item of a section; it only draws between items of the same section. The gap after the last item is the job of `SectionSeparatorComponent`, which renders after a section's last item and before its first.
  • Why does a separator passed as <View style={styles.line} /> never receive highlighted?
    When a separator is given as an element, the list renders that element as-is. Only the component form, such as `ItemSeparatorComponent={ArtistLine}`, is rendered with `highlighted`, `section` and the leading and trailing props injected.

saying these in an interview costs you the question

  • ItemSeparatorComponent also renders between the last item and the next section header.
  • SectionSeparatorComponent renders only once, between two sections.
  • Separators passed as elements still receive the highlighted prop.
  • An empty section renders its section separators around the header.
  • SectionSeparatorComponent can be overridden on each section object.