extraData and Re-Rendering

FlatList is a PureComponent: when its parent re-renders, it re-renders only if one of its own props changed. That is fast, and it causes a classic bug. If renderItem depends on something that is not a prop, such as a selected id kept in a store, the list never learns that it changed. extraData is the escape hatch: pass the value, or a version number, and the list re-renders when it changes. This demo keeps the selection in a plain object and bumps version on every tap:

src/Selectable.tsx: selection kept outside the list's props (excerpt)TSX
const store = { selectedId: 0 };    // state kept outside React, as a store library would
const USE_EXTRA_DATA = true;
const keyExtractor = (b: Book) => String(b.id);
// ...
  const renderItem = useCallback(({ item }: { item: Book }) => (
    <LoggedRow book={item} selected={item.id === store.selectedId} onPress={select} />
  ), [select]);
  return (
    <FlatList data={books} keyExtractor={keyExtractor} renderItem={renderItem}
      extraData={USE_EXTRA_DATA ? version : undefined} />

LoggedRow is a memoized BookRow that logs each render. After the first six renders, a tap on Salt and Saffron logged one line with extraData and nothing without it, where the row also stayed unhighlighted:

Output of 73
 LOG  render book 3, selected=true

Only the changed row rendered, because memo skipped the rest. A first version of this demo passed keyExtractor={(b) => String(b.id)} inline, and then the row highlighted either way: the new function was a changed prop, so the list re-rendered on every parent render and hid the bug. Stable props make FlatList cheap; extraData tells it when stability is lying.