Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solutions for infiniteScrolling onEndReached firing when it shouldn't #38

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

faceyspacey
Copy link

this ended up being a way bigger trek than I anticipated. Basically, i found a bunch of edge cases which cause onEndReached to fire when it shouldn't. I used the responder system and datetime flags to figure out what the user's likely intent is in as many scenarios as I encountered. My app using this is now squeaky clean--no extra async calls to my server. Detailed notes are in the comments. There is also a few new features and refactorings. This isn't tested for Android, only iOS. But if Android infinite scroll was already working, we just need to make sure this doesn't conflict.

this ended up being a way bigger trek than I anticipated. Basically, i found a bunch of edge cases which cause onEndReached to fire when it shouldn't. I used the responder system and datetime flags to figure out what the user's likely intent is in as many scenarios as I encountered. My app using this is now squeaky clean--no extra async calls to my server. Detailed notes are the comments. There is also a few new features and refactorings. This isn't tested for Android, only iOS. But if Android infinite scroll was already working, we just need to make sure this doesn't conflict.
this is primarily for usage with redux. the idea being that your `onFetch` prop will dispatch a redux action that ultimately will reduce the returns rows to the `rows` prop passed to GiftedListView, and when new rows are received, `componentWillReceiveProps` will serve the same purpose as the callback originally passed to `onFetch`. Therefore, onFetch doesn't ever need to call this callback (even though it will still receive it). When all rows are loaded just set the `allLoaded` prop to `true`. 

The only thing worth noting in the implementation is how the `beforeOptions` are kept in tack. Before they were passed to onFetch which ultimately passes them back, and possibly adds `allLoaded`, but now we store them on the instance at `this.beforeOptions`, resulting in calling code not having to worry about it at all, unless it wants to set `allLoaded` to true as described above. 

In addition, there's a `fetchOptions` prop which can be used to trigger a refresh, and then the calling of `onFetch` with the new params, which you can use to dispatch and make async queries which will ultimately reduce a new `rows` prop. The idea being that the interface used in its simplest most effective form consists of you just changing your `fetchOptions` :).
@kdenz
Copy link

kdenz commented Jul 8, 2016

@faceyspacey Hi! This infinite scrolling looks great! Any example for how to implement it? I copied the exact code and although it loads, the auto pagination feature doesn't seem to work. It shows me I've reached the end of list when in fact I haven't. I simply added "autoPaginate: true" to the sample code.

Anyway, thanks for your efforts man, I've no clue why smooth, well-documented infinite scrolling has yet to be included in any repository, lol. It's such a great feature most modern day apps deserve!

//start
_onFetch(page = 6, callback, options) {
    setTimeout(() => {
      var rows = ['row '+((page - 1) * 3 + 1), 'row '+((page - 1) * 3 + 2), 'row '+((page - 1) * 3 + 3)];
      if (page === 6) {
        callback(rows, {
          allLoaded: true, // the end of the list is reached
        });
      } else {
        callback(rows);
      }
    }, 1000); // simulating network fetching
  },


  /**
   * When a row is touched
   * @param {object} rowData Row data
   */
  _onPress(rowData) {
    console.log(rowData+' pressed');
  },

  /**
   * Render a row
   * @param {object} rowData Row data
   */
  _renderRowView(rowData) {
    return (
      <TouchableHighlight
        style={styles.row}
        underlayColor='#c8c7cc'
        onPress={()=>this._onPress(rowData)}
      >
        <Text>{rowData}</Text>
      </TouchableHighlight>
    );
  },

  render() {
    return (
      <View style={styles.container}>
        <GiftedListView
          rowView={this._renderRowView}
          onFetch={this._onFetch}
          firstLoader={true} // display a loader for the first fetching
          pagination={true} // enable infinite scrolling using touch to load more
          refreshable={true} // enable pull-to-refresh for iOS and touch-to-refresh for Android
          withSections={false} // enable sections
          **autoPaginate={true}**
          customStyles={{
            paginationView: {
              backgroundColor: '#eee',
            },
          }}

          refreshableTintColor="blue"
        />
      </View>
    );
  }
}); 
//end

@kdenz
Copy link

kdenz commented Jul 8, 2016

@faceyspacey

Also I realised in order to work for me (RN 27.2), the import code has to be structured as follows:

var React = require('react');

var {
  ListView,
  Platform,
  TouchableHighlight,
  View,
  Text,
  RefreshControl,
  ScrollView,
} = require('react-native');

import shallowCompare from 'react/lib/shallowCompare';

@kdenz
Copy link

kdenz commented Jul 8, 2016

@FaridSafi Hi man, the whole gifted repositories are great! Thanks a lot!
If this autoscroll feature can be implemented, I believe it'll make this even better! ;)

@brunoksato
Copy link

+1

@waleedarshad-vf
Copy link

When will it be implemented?

@eul721
Copy link

eul721 commented Oct 28, 2016

If it's still relevant, I was able to fix the problem where the list reaches an end even when there's still data available.
By changing

_updateRows(rows = [], options = {}, isRefresh=false) {
    let state = {
      paginationStatus:
        (options.allLoaded === true
          || rows.length === 0
          || rows.length % this.props.limit  === 0 // Changed from !== to ===
          || (this._prevRowsLength === rows.length && !isRefresh)
          || (this.props.limit && rows.length < this.props.limit)
        ) ? 'allLoaded' : 'waiting',
    };
...

Great library and great addition of feature! Hopefully these changes make it into the master soon :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants