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.

Flatlist performance slow

See original GitHub issue

Description

I’m using FlatList to load some records. Above the FlatList I have a button and when I tap this button with 230 items loaded in the FlatList, the performance gets horrible.

I’m using a Smartphone ASUS Zenfone Go LTE ZB500KL-1A058BR with android 6.0

I’ve created a video to better illustrate: http://www.youtube.com/watch?v=EIlDnoewVhc

My code:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  FlatList,
  TouchableOpacity,
  TextInput,
  TouchableWithoutFeedback,
} from 'react-native';

const GLOBAL_DATA = [];
const PER_PAGE = 10;

const paginateArray = (array, pageSize, pageNumber) => {
  const _pageNumber = pageNumber - 1;
  return array.slice(_pageNumber * pageSize, (_pageNumber + 1) * pageSize);
};

for (let i = 0; i <= 1000; i++) {
  GLOBAL_DATA.push({
    key: i,
    produto: {
      descricao: 'Item number ' + i,
    }
  });
}

export default class flatlistdemo extends Component {
  constructor(props) {
    super(props);
  
    this.state = {
      type: 'default',
      data: [],
      page: 1,
    };
  }

  componentDidMount() {
    this.setState({
      data: paginateArray(GLOBAL_DATA, PER_PAGE, this.state.page),
    });
  }

  getPagedOffers = () => {
    this.setState((state) => ({
      data: state.data.concat( paginateArray(GLOBAL_DATA, PER_PAGE, this.state.page) ),
    }));
  }

  handleLoadMore = () => {
    this.setState(
      {
        page: this.state.page + 1,
      },
      () => {
        this.getPagedOffers();
      }
    );
  }

  renderType = () => {
    if (this.state.type === 'default') {
      return (
        <View>
          <TouchableOpacity 
            onPress={() => {
              this.setState({
                type: 'other'
              });
            }}
            style={{backgroundColor: 'black', padding: 10}}
          >
            <Text
              style={{color: '#fff'}}
            >
              touch here to change the type 01
            </Text>
          </TouchableOpacity>
        </View>
      );
    } else {
      return (
        <View>
          <TouchableOpacity 
            onPress={() => {
              this.setState({
                type: 'default'
              });
            }}
            style={{backgroundColor: 'blue', padding: 10}} 
          >
            <Text
              style={{color: '#fff'}}
            >
              touch here to change the type 02
            </Text>
          </TouchableOpacity>
        </View>
      );
    }
  }

  render() {
    return (
      <View style={styles.container}>
        {this.renderType()}
        <FlatList
          data={this.state.data}
          onEndReached={this.handleLoadMore}
          onEndReachedThreshold={50}
          getItemLayout={(data, index) => (
            {length: 40, offset: 40 * index, index}
          )}
          renderItem={
            ({item}) => {
              return (
                <View 
                style={{
                  paddingVertical: 10,
                }}>
                  <TouchableOpacity onPress={() => null}>
                    <Text 
                      style={{
                        color: '#000', 
                        height: 40,
                        justifyContent: 'center'
                      }}>
                      {item.produto.descricao}
                    </Text>
                  </TouchableOpacity>
                </View>
              );
            }
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop: 30,
    alignItems: 'center',
  },
});

AppRegistry.registerComponent('flatlistdemo', () => flatlistdemo);

Solution

Maybe something is wrong with my display: none / block?

Additional Information

  • React Native version: 0.43.4
  • Platform: Android 6.0
  • Development Operating System: MacOS Sierra
  • Dev tools: Xcode

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:10
  • Comments:12

github_iconTop GitHub Comments

97reactions
navid94commented, Apr 25, 2017

I think that you have to create a React.PureComponent for each item that you render in renderItem:

class MyListItem extends React.PureComponent {
  render() {
    return (
        <View 
                style={{
                  paddingVertical: 10,
                }}>
                  <TouchableOpacity onPress={() => null}>
                    <Text 
                      style={{
                        color: '#000', 
                        height: 40,
                        justifyContent: 'center'
                      }}>
                      {this.props.produto.descricao}
                    </Text>
                  </TouchableOpacity>
                </View>
    )
  }
}

_renderItem = ({item}) => (
    <MyListItem
         produto={item.produto}
    />
  );

<FlatList
          data={this.state.data}
          onEndReached={this.handleLoadMore}
          onEndReachedThreshold={50}
          getItemLayout={(data, index) => (
            {length: 40, offset: 40 * index, index}
          )}
          renderItem={this._renderItem}
        />

This should make performance much better since items will not update everytime, as suggested here http://facebook.github.io/react-native/releases/0.44/docs/flatlist.html (doc version 0.44). Otherwise you can use http://facebook.github.io/react-native/docs/virtualizedlist.html#shoulditemupdate , but it will be deprecated in 0.44 in favor of React.PureComponent. Before using PureComponent read the following:

This is a PureComponent which means that it will not re-render if props remain shallow- equal. Make sure that everything your renderItem function depends on is passed as a prop that is not === after updates, otherwise your UI may not update on changes. This includes the data prop and parent component state.

7reactions
gregblasscommented, Dec 7, 2017

Are functional components even better in this case than pure components? My list items don’t need state at all, so I figured that would be the most performant solution? Or are they going to be not as efficient as a pure component for some reason?

EDIT: Functional components are not better in cases like this. You want to use pure components or shouldComponentUpdate.

Read more comments on GitHub >

github_iconTop Results From Across the Web

react native 100+ items flatlist very slow performance
I have a list just simple text that rendering into flatlist on react native but I am experiencing very very slow performance which...
Read more >
Optimizing Flatlist Configuration - React Native
The heavier your components are, the slower they render. Avoid heavy images (use a cropped version or thumbnail for list items, as small...
Read more >
React Native: Optimizing FlatList performance
Flatlist is react-native component should be used for rendering scrollable lists. If you don't optimize well enough, performance starts to ...
Read more >
8 ways to optimize React native FlatList performance
8 ways to optimize React native FlatList performance · 1. Avoid arrow functions inline for renderItem · 2. Don't use 1080P HD images...
Read more >
FlatList very slow on Android only · Issue #33542 - GitHub
Description. I am experiencing a very slow FlatList on Android, despite the fact that I reduced my renderItem component to just text: FlatList:....
Read more >

github_iconTop Related Medium Post

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