wix / react-native-calendars

React Native Calendar Components 🗓️ 📆
MIT License
9.35k stars 2.91k forks source link

For Anyone Using AgendaList - Discussion around bidirectional pagination #2325

Open jakehasler opened 9 months ago

jakehasler commented 9 months ago

I wanted to take a few minutes and outline my findings over the last 4ish weeks using ExpandableCalendar and AgendaList in conjunction with one another.

There have been many comments about the performance of the standard AgendaList (issues here), and I found that to be the case with my situation as well -- it was painfully slow and jumpy and was not the quality I want my users to have.

The number 1 best solution to this is using the new InfiniteAgendaList that's been implemented (but not documented). When I started using it, performance improved drastically and it made my app feel incredibly snappy and native. The way to do this is to pass an infiniteListProps object with itemHeight and headerHeight to your AgendaList and then it will switch over to rendering. (in my case, my heights were dynamic so I added a calculateHeaderHeight and calculateItemHeight to the library so I can use them in the props, I may create a PR for this).

The InfiniteAgendaList uses a RecyclerListView which is a dependency/predecessor to Shopify's FlashList and has the same creator (@naqvitalha).

Things have going along extremely well in my testing and initial implementation. When my calendar screen loaded, I was building an array of 7 days prior and 30 days in the future so that the list could render, and then loading in the calendar events from my server to populate into the populated days. The underlying RecyclerListView even has an initialRenderIndex prop that will allow you to render right to Today's date on load if you know the index.

I ran into a potentially deal-breaking issue yesterday when I wanted to start implementing pagination to the AgendaList so I could navigate around to any date, like you would in any calendar app. I got forward pagination working well simply by using onEndReached and then generating a fresh array of future dates and subsequently loading in my calendar events for the same date range that got generated. But as soon as I started working on pagination to previous dates, things started getting complicated. When I generated and loaded in the previous dates and tried prepending them to the array, the list would jump to the top of the list instead of just adding the items above the current scroll position. So for example, the beginning of my list would be Sept. 19th and when I'd scroll up to that date (determined by offsetY scroll position provided by the onScroll method), I'd prepend the previous 30 days and the list would instantly show August 20 at the top of the list.

Prepending items to a list isn't a new or novel concept - it's very common in messaging apps as you scroll back through history, though it seems to be something that has been a struggle for react native. RN core's ScrollView and SectionList have a prop called maintainVisibleContentPosition that does what it says, holds the list at the current position when items get added to the data. But even that hasn't had android support until RN. 0.72. And FlatList doesn't support it, though this community library, https://github.com/GetStream/flat-list-mvcp, seems to have it nicely available.

Both RecyclerListView and FlashList don't have support for this feature/prop (see here, here and here)

Ultimately, I'm not sure where to go from here. I'm writing this as a topic for general discussion/call for help to see if anyone has any thoughts or ideas on how to achieve this functionality. My current thoughts are to try and leverage the initialOffset prop in the RCV (as mentioned in this comment) and if that doesn't work, then I may end up tearing out the RCV and replacing it with the adapted FlatList library mentioned above.

My aim is absolute not to criticize or belittle anyone who has worked on these projects. There is a reason I'm not the one building them - I'm not smart enough or dedicated enough to build out such complex projects designed for so many use cases. This (and the underlying lists) are fantastic libraries that have saved me a lot of time and I'm really grateful for them.

Let me know your thoughts and ideas. Thanks!

p.s. I'm maintaining my own fork of the library here. It has some specific changes for my needs and also my autoformatter is reflecting a lot more changes then there should be, I need to get that fixed. But anyone's welcome to use it as a reference.

damonbauer commented 7 months ago

I've run into this using AgendaList as well. From my testing, there's a bug in React Native where SectionList does not honor the maintainVisibleContentPosition prop when scrolling up. React Native 0.72 introduced that prop for Android, as well as introduced an onStartReached prop (the corollary to onEndReached)... I was hopeful this would "just work" out of the box, but it doesn't.

Here's a reproducible example: https://snack.expo.dev/@damon_bauer/arrogant-green-bananas

When the top of the list is reached I'm calling onStartReached which prepends data to the sections passed to SectionList. This causes the SectionList to jump to the top of list, which fires onStartReached again... and it's an endless loop.

This happens on both iOS and Android.


The only way I can figure out how to work around this issue is to use a Flatlist instead of a SectionList, which means forking the react-native-calendars repo...

(For reference, here's a React Native issue with this bug)

yashsongara101 commented 6 months ago

@damonbauer This is happening with me also. Tried with section list.

stale[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.