Skip to content

FlatList ItemSeparatorComponent doesn't re-render when item change #24592

@brunolemos

Description

@brunolemos

🐛 Bug Report

FlatList's ItemSeparatorComponent receives a leadingItem prop, but when this item change the ItemSeparatorComponent doesn't get updated with the new leadingItem value.

To Reproduce

  • Create a FlatList with ItemSeparatorComponent
  • Make the ItemSeparatorComponent render different colors based on the received leadingItem
  • Change the item at runtime
  • ItemSeparatorComponent doesn't update

Expected Behavior

ItemSeparatorComponent should re-render when the leadingItem change as the default behavior.

Code Example

https://snack.expo.io/@brunolemos/itemseparatorcomponent-bug

See code
import * as React from 'react';
import { Button, View, StyleSheet, FlatList } from 'react-native';

export default class App extends React.Component {
  state = {
    items: [
      { id: 1, isRead: false },
      { id: 2, isRead: false },
      { id: 3, isRead: true },
      { id: 4, isRead: true },
      { id: 5, isRead: true },
      { id: 6, isRead: false },
      { id: 7, isRead: false },
      { id: 8, isRead: false },
      { id: 9, isRead: false },
      { id: 10, isRead: false },
    ],
  };

  renderItem = ({ item }) => (
    <View
      style={{
        flex: 1,
        height: 50,
        backgroundColor: item.isRead ? '#999999' : '#CCCCCC',
      }}
    />
  );

  renderSeparator = ({ leadingItem }) => (
    <View
      style={{
        width: '100%',
        height: 2,
        backgroundColor: leadingItem && leadingItem.isRead ? 'black' : 'blue',
      }}
    />
  );

  render() {
    return (
      <View style={styles.container}>
        <FlatList
          ItemSeparatorComponent={this.renderSeparator}
          data={this.state.items}
          renderItem={this.renderItem}
          style={{ flex: 1 }}
        />

        <Button
          title="Mark all as read"
          onPress={() =>
            this.setState(state => ({
              items: state.items.map(item => ({ ...item, isRead: true })),
            }))
          }
        />
        <Button
          title="Mark all as unread"
          onPress={() =>
            this.setState(state => ({
              items: state.items.map(item => ({ ...item, isRead: false })),
            }))
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: 21,
    backgroundColor: '#ecf0f1',
  },
});

GIF: Item separator is black when item is marked as read, and blue when not. When marking all items as read, all separators should turn black, but they are not being re-rendered.

Environment

See Environment

React Native Environment Info:
System:
OS: macOS 10.14.4
CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
Memory: 61.35 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 11.5.0 - /usr/local/bin/node
Yarn: 1.13.0 - ~/.yarn/bin/yarn
npm: 6.7.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
Android SDK:
API Levels: 19, 22, 23, 24, 25, 27, 28
Build Tools: 23.0.1, 23.0.3, 24.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.2, 26.0.3, 27.0.0, 27.0.1, 27.0.2, 27.0.3, 28.0.0, 28.0.2, 28.0.3
System Images: android-19 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.3 AI-182.5107.16.33.5314842
Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
npmGlobalPackages:
react-native-git-upgrade: 0.2.7

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions