reactjsreactjs-fluxreact-nativereact-native-listview

React Native ListView performance is too slow?


I have 113 records in my application.react native listView is taking more than 3 seconds to render all the rows. how can i make it efficient so time consumption can be minimum and app experience can be smooth. i have checked the same application in ios and it is much efficient as compared to react-native app version. I have one avatar image and name and button in each row.

Here is my code for listview

var Ziglist = React.createClass({
getInitialState: function() {
     return {
        isLoading: true,
        resultsData: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 != row2 }),
      };
},

componentWillMount: function(){
  PeopleStore.listen(this.onChange);
  PeopleActions.getPeopleFollowing();
},

componentWillUnmount() {
  PeopleStore.unlisten(this.onChange);
},

onChange(state) {
this.setState({resultsData: this.getDataSource(state.resultsData)})
},

getDataSource: function(mediaItem: Array<any>): ListView.dataSource {
  return this.state.resultsData.cloneWithRows(mediaItem)
},
render: function() {
    return (
  <View style={{flex: 1}} >
  <ListView
    dataSource={this.state.resultsData}
    renderRow={this.renderRow}
    renderSeperator={this.renderSeperator}
    contentInset={{top: 0}}
    automaticallyAdjustContentInsets={false}
  />
  <Button
    containerStyle={styles.goAhead}
    style={styles.base}
    onPress={() => this.onStartPress()}>
    <Text style={[styles.base,styles.go]}>Ok, Lets GO > </Text>
  </Button>
 </View>
);
},
renderSeparator: function (sectionID: number | 
string, rowID: number | string, adjacentRowHighlighted: boolean ) {
 return (
    <View key={"SEP_" + sectionID + "_" + rowID} />
 );
},
renderRow: function (
 media: Object,
 sectionID: number | string,
 rowID: number | string,
 highlightRowFunction: (sectionID: ?number | string, 
 rowID: ?number | string) => void,) {
  return (
    <CelebrityRow
     media={media}
     onSelect={() => this.selectMediaItem(media)}
     onHighlight={() => highlightRowFunction(sectionID,rowID)}
     onDeHighlight={() => highlightRowFunction(null,null)}
    />
 );
},
selectMediaItem: function (mediaItem) {
this.props.navigator.push({
  name: 'celebrityDetailView',
  passProps: {
    mediaItem: mediaItem
  }
});
}

and here is the code for Celebrity Row

var CelebrityRow = React.createClass({
getInitialState: function() {
    return {
        following_ids: FollowingStore.getState().following_ids,
        unfollowing_ids: FollowingStore.getState().unfollowing_ids,
        icon: null,
        follow: true
    }
},
componentWillMount: function() {
    if (_.indexOf(this.state.unfollowing_ids, this.props.media.id) > -1) {
        this.setState({
            follow: !this.state.follow
        });
    }
},
componentWillUnmount: function() {},
componentDidMount: function() {
    var _unfollowing_ids = FollowingStore.getState().unfollowing_ids;

    if (_unfollowing_ids.length > 0 && this.state.follow === false) {
        var following_arr = PeopleStore.getState().resultsData;
        var _following_ids = FollowingStore.getState().following_ids;

        _.each(_unfollowing_ids, function(id) {
            var find = _.findWhere(following_arr, {
                id: id
            });
            following_arr = _.without(following_arr, find);
        });

        var following_ids = _.difference(_following_ids, _unfollowing_ids);

        this.setState({
            unfollowing_ids: [],
            following_ids: following_ids
        });
        var _this = this;
        setTimeout(function() {
            FollowingActions.updateFollowingIdsWithStorage(following_ids);
            FollowingActions.updateUnFollowingIds([]);
            PeopleActions.updatePeopleFollowingWithStorage(following_arr);
            _this.setState({
                follow: true
            })
        }, 1000);

    }

},
onChange: function(state) {
    // this.setState({unfollowing_ids: state.unfollowing_ids});
},
onAddPress: function(media) {

    this.setState({
        follow: !this.state.follow
    });
    FollowingActions.updateUnFollowingIds(media.id);
},
render: function() {

    return ( <
        View style = {
            styles.row
        } >
        <
        TouchableHighlight onPress = {
            this.props.onSelect
        }
        onShowUnderlay = {
            this.props.onHighlight
        }
        onHideUnderlay = {
            this.props.onDeHighlight
        } >
        <
        View style = {
            styles.cellContainer
        } >
        <
        Image source = {
            {
                uri: this.props.media.avatar_url
            }
        }
        style = {
            styles.cellImage
        }
        /> <
        Text style = {
            styles.CelebrityName
        }
        numberOfLines = {
            1
        } > {
            this.props.media.name
        } < /Text>

        <
        View style = {
            styles.celebrityAdd
        } >
        <
        Button onPress = {
            () => this.onAddPress(this.props.media)
        } > {
            (this.state.follow ?
                ( <
                    Image source = {
                        require("../assets/tick-mark.png")
                    }
                    style = {
                        styles.addIcon
                    }
                    />
                ) : ( <
                    Image source = {
                        require("../assets/img-small-add.png")
                    }
                    style = {
                        styles.removeIcon
                    }
                    />
                )
            )
        } <
        /Button> <
        /View>

        <
        /View> <
        /TouchableHighlight> <
        /View>

    );
}

});


Solution

  • Instead of render the whole 100+ rows at once, you can set initialListSize prop to increase the rendering performance.

    reference : http://facebook.github.io/react-native/releases/0.30/docs/performance.html#listview-initial-rendering-is-too-slow-or-scroll-performance-is-bad-for-large-lists