ReactNative ListView setting initial scroll position after data loaded
Asked Answered
S

1

11

I have an events section which has section headings containing the date. I need to be able to jump to specific dates, as well as have the initial scroll position set to the first date in the future.

In order to jump to specific dates I have tried storing their y positions in state.

renderSectionHeader= (sectionData, sectionID) => (
      <View
        onLayout={(event) => {
          const { y } = event.nativeEvent.layout;
          const sectionPosition = { [sectionID]: y };
          const sectionPositions = Object.assign({}, this.state.sectionPositions, sectionPosition);
          this.setState({ sectionPositions });
        }}
       ...

I ran into problems with this approach though as renderSectionHeader is not called on elements which are further down the list (due to the lazy rendering).

I have then tried calculating the position mathematically , but this then causes the rendering of each section to show on screen while it is moving closer to the given date.

Is there a way of achieving what I need?

RELATED

React Native ListView: How to scroll to a particular row

https://github.com/facebook/react-native/issues/499

UPDATE

In my app I know all the rows are the exact same height.

Using contentOffset={{ y: offsetY }} rather than setScroll does not work, since it still needs to render all items up to the given item to work.

Using initialListSize={99999999} does work, but makes the page very slow, and I have been warned against using it.

UPDATE 2

Is it possible to provide my initial content to datasource, and then update the data to add extra items in before and after the elements currently on screen?

Or is there a library I haven't found which does what I need?

Senzer answered 18/7, 2016 at 11:13 Comment(12)
If u store the y positions before the data loaded, so they r irrelevant anymore, right?Vasques
The y positions stored are fine and I can scroll to these, the issue is only some of the section headers are rendered due to lazy rendering, so I cant scroll to items further down the listSenzer
"‘you can’t have your cake and eat it'", If u want lazy loading so this is the meaning of it, u r lazy on loading the whole listView. I assume that even on native (iOS) u'll have this problem.Vasques
Just tried setting initialListSize to a huge number, this sort of works, although it then takes ages to load the page. Maybe it wont be so bad in release ...Senzer
"Just tried setting initialListSize to a huge number" - do NOT do this, it will lead to psychotic stuff.Vasques
What would you recommend? I guess I could do the same with scrollRenderAheadDistance? What stuff might happen? I need the sticky section headers from a listview, but I also need to be able to scroll to any section ...Senzer
mmm, sound to me a bad product to jump to section. If I had this problem I was try to rethink about the product since u try to abuse the usage of listView. I think that jump to position isn't the best UX. Maybe instead of jump to... try to add an index screen and push the selected one. But again, It's just my small opinion :)Vasques
There is already an existing native app which I'm trying to recreate so I do need this behaviour unfortunatelySenzer
Instead of setting initialListSize={99999999} you can try setting it to the index of the desired item, plus a screen worth of it.Entoblast
hey I know it's been a while but did you find a solution? I've facing the same problem here #69731519Caribbean
@cakelover yes the flatlist :)Senzer
@Senzer any idea how to solve it?Caribbean
S
6

It looks like this may soon be solved by FlatList which is currently in the experimental folder in the React-Native repo.

https://github.com/facebook/react-native/blob/a3457486e39dc752799b1103ebe606224a8e8d32/Libraries/Experimental/FlatList.js

Better ListView - FlatList Summary: We really need a better list view - so here it is!

Main changes from existing ListView:

  • Items are "virtualized" to limit memory - that is, items outside of the render window are unmounted and their memory is reclaimed. This means that instance state is not preserved when items scroll out of the render window.
  • No DataSource - just a simple data prop of shape Array<any>. By default, they are expected to be of the shape {key: string} but a custom rowExtractor function can be provided for different shapes, e.g. graphql data where you want to map id to key. Note the underlying VirtualizedList is much more flexible.
  • Fancy scrollTo functionality: scrollToEnd, scrollToIndex, and scrollToItem in addition to the normal scrollToOffset.
  • Built-in pull to refresh support - set set the onRefresh and refreshing props.
  • Rendering additional rows is usually done with low priority, after any interactions/animations complete, unless we're about to run out of rendered content. This should help apps feel more responsive.
  • Component props replace render functions, e.g. ItemComponent: ReactClass<{item: Item, index: number}> replaces renderRow: (...) => React.Element<*>
  • Supports dynamic items automatically by using onLayout, or getItemLayout can be provided for a perf boost and smoother scrollToIndex and scroll bar behavior.
  • Visibility callback replaced with more powerful viewability callback and works in vertical and horizontal mode on at least Android and iOS, but probably other platforms as well. Extra power comes from the viewablePercentThreshold that lets the client decide when an item should be considered viewable.

Demo:

enter image description here

Senzer answered 9/2, 2017 at 16:39 Comment(1)
I tried using FlatList and it works great. Wanted to add a minutia of something that I figured out: My scrolling was off at first, and then I added this to my main view: <View style={{flex:1}}>. By setting the parent to take up the full view, the child knows how much room to take up. Thought I'd give that pointer/heads-up to people like me, iOS developers learning React.Horripilate

© 2022 - 2024 — McMap. All rights reserved.