question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using FlatList with item component wrapped with react-redux connect()

See original GitHub issue

Description

I’ve followed the guide at https://facebook.github.io/react-native/docs/flatlist.html to implement a FlatList. My implementation is essentially the same as the example provided in this guide under “More complex example”, except that my <MyListItem /> component has been wrapped with the react-redux connect() function in order to pass down some additional props to the component (some props from state, and some props that are functions that use dispatch). This seems to be working correctly, however the docs don’t make it clear whether this pattern is okay. Will this cause any issues with FlatList?

Sample Code

Here’s the example from the FlatList guide, modified to demonstrate how I’m wrapping my item component with connect().

class MyListItem extends React.PureComponent {
  _onPress = () => {
    this.props.onPressItem(this.props.id);
    this.props.myClickHandler(this.props.myProp);
  };

  render() {
    return (
      <SomeOtherWidget
        {...this.props}
        onPress={this._onPress}
      />
    )
  }
}

MyListItem = connect(state => ({
  myProp: state.myProp,
}), {
  myClickHandler,
})(MyListItem);

class MyList extends React.PureComponent {
  state = {selected: (new Map(): Map<string, boolean>)};

  _keyExtractor = (item, index) => item.id;

  _onPressItem = (id: string) => {
    // updater functions are preferred for transactional updates
    this.setState((state) => {
      // copy the map rather than modifying state.
      const selected = new Map(state.selected);
      selected.set(id, !selected.get(id)); // toggle
      return {selected};
    });
  };

  _renderItem = ({item}) => (
    <MyListItem
      id={item.id}
      onPressItem={this._onPressItem}
      selected={!!this.state.selected.get(item.id)}
      title={item.title}
    />
  );

  render() {
    return (
      <FlatList
        data={this.props.data}
        extraData={this.state}
        keyExtractor={this._keyExtractor}
        renderItem={this._renderItem}
      />
    );
  }
}

Solution

Clarify whether this pattern would cause any issues. It’s my understanding that ListView (which FlatList replaces) had some optimisation techniques where the React Components that correspond with the items in the list (one Component per item) are not fully deleted/recreated from memory when they come in to the visible area of the screen (or leave this area), and instead the same Components that have already been rendered are retained in memory and injected with the new props of the new list item. Assuming this is correct and that this sort of optimisation is still being done in FlatList, I’m unsure whether this optimisation technique (or any other implementation detail of FlatList) would conflict with using connect() to wrap the FlatList item component.

Additional Information

  • React Native version: 0.45.1
  • Platform: Both
  • Development Operating System: macOS
  • Build tools: Xcode 8

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:4
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
mrkpatchaacommented, Aug 19, 2017

This is not working if the data needed by MyListItem is not already in the redux state. Imagine that in MyListem item you have to call a function to explicitly load this data.

componentDidMount = () => {
    this.props.getData();
};

The action will be executed but when the data is pushed in the redux store, MyListItem is not re-rendered because it is a PureComponent. componentWillUpdate and componentWillReceiveProps are not fired.

You must find a way to tell Flatlist to explicitly re-render this component.

I am facing this issue actually and I will post a solution if I find one 😃

2reactions
walty8commented, Oct 5, 2017

@rmkpatchaa I finally solved the problem by passing extraData={this.props} into the flat list, see this for more details.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React redux updates flatlist item but turns item into an Array
For the feed being an array, look closely at your code. You'll see you have wrapped the value of feed in square brackets...
Read more >
FlatList - React Native
FlatList. A performant interface for rendering basic, flat lists, supporting the most handy features: Fully cross-platform.
Read more >
Comprehensive guide to using Redux in React Native
To render the movie items, we'll use the FlatList component from React Native. It accepts the movies array as the value of the...
Read more >
Display a List Using the FlatList Component in React Native
React Native's `FlatList` component renders list items that can be displayed on the screen, and has features like scrolling, header/footer ...
Read more >
How to use Redux with React Native - Able
React Hooks provide us the ability to use functional components in ... boilerplate code when using the connect() High Order Component (if ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found