React Native - Pagination of ListViews in ScrollView?
Asked Answered
C

3

15

I have 3 ListView components inside a single ScrollView component like this:

<ScrollView>
  <Header />
  <ListView onEndReached={() => alert('load more 1')}/>
  <ListView onEndReached={() => alert('load more 2')}/>
  <ListView onEndReached={() => alert('load more 3')}/>
  <Footer />
</ScrollView>

The Header component has some common content and also has 3 tabs, which trigger showing the respective ListView

The issue is any ListView with onEndReached={() => alert('load more 1')} never runs the alert, so I can never load more as I scroll down and hit the end of the listview. Remove the wrapping ScrollView and the alert runs, but the common Header doesn't scroll, since we just removed the wrapping ScrollView. The header needs to scroll with the listview, which is why I wrapped everything that needs to scroll in the ScrollView.

IMPORTANT NOTE: I can't really use ListView with renderHeader={this.header}, for this scenario. Because, even though the Header will scroll, it will rerender the common Header and the 3 tabs for each ListView each time a ListView renders, instead of once. So a new Header rerender each time for each ListView won't cut it for the app.

Looking for a solution to this problem, where the Header scrolls with the listviews and the onEndReached is triggered for the visible ListView.

Compurgation answered 11/8, 2016 at 4:13 Comment(3)
Do you need the header tabs to animate at all when switching between them (e.g. The example shows the top and bottom lines animating)Ecclesiasticus
Also, if you don't need the Header to animate - why is it a problem for you if the Header re-renders in each ListView, so long as the state persists?Ecclesiasticus
@Luke Rhodes No need to animate the header when switching, but I don't want the header to re-render for each list view on tab change, because it shows white where the header is as it re-renders, but only the bottom parts (listview) is what should change along with the appropriate tab selected.Compurgation
B
2

I think you're going to have to solve this by changing the dataSource in each listView in response to what header element is selected instead of loading three different ListViews.

getInitialState() {
    return {
        currentList: this.ds.cloneWithRowsAndSections(INITIAL_DATA);
    }
},
render() {
    return <ListView renderHeader={this._renderHeader} dataSource={this.state.currentList}/>
}

The only reason you wouldn't want to do this is if you wanted to maintain the scroll position in the three sub ListViews, but that wouldn't be useful because you always have to scroll to the top to change which ListView you're looking at anyway.

Then in your _renderHeader function you would render a selector that populates currentList with different data depending on the header selected.

Bunting answered 6/9, 2016 at 7:10 Comment(1)
Yes! The header now scrolls with the content, loads more when I get to bottom, and doesn't "white flash" the header as it re-renders the listview. Great solution! Thank you frank :)Compurgation
Z
0

In styling you can set it's position as relative with top:0 and left:0 . This way it will remain static on top.

<View>
<Header style={{position:"relative",top:0,left:0,height:30,width:Dimensions.get("window").width}} />
  <ListView />
  <ListView />
  <ListView />
 <Footer />
 </View>

Second option which may work in scrollview is to specify height for all three ListView.

Zohar answered 11/8, 2016 at 4:49 Comment(1)
Thank you for your response while1. Option 1 won't scroll the Header I think since it's not in a ScrollView, and I need the header to scroll away as you scroll down. I meant by static, that it should not be rerendered, but still scroll with the body. Option 2, it's a dynamic size and loads more as you go, so not sure how the heights will work there.Compurgation
C
0

You can maybe use ScrollView::onScroll but it will be a little hacky. You will need to know the size of your listviews.

Work with ListView only

Maybe the best solution will be to play with the ListView dataSource and the onEndReached function.

If you update you dataset when ListView::onEndReached is triggered, I think you can add more elements to your ListView. This way, you do not need to do hacky things with ListViews in ScrollViews.

Cracknel answered 6/9, 2016 at 7:16 Comment(1)
The issue is it could be dynamic height of list view items (may be a bit different height for each element), so the solution needs to be flexible. Working with listviews only won't scroll the header either, see Important Note in question for the header re-rendering again issue when using listviews only.Compurgation

© 2022 - 2024 — McMap. All rights reserved.