react-native-snap-carousel icon indicating copy to clipboard operation
react-native-snap-carousel copied to clipboard

How to load large data set (2000 items) with smooth scrooling between item cards

Open kirtishjain9 opened this issue 4 years ago • 15 comments

Is this a bug report, a feature request, or a question?

I don't know whether it's a bug or implementation issues but need an effective solution.

Is the bug specific to iOS or Android? Or can it be reproduced on both platforms?

iOS 12.2 & higher.

Is the bug reproductible in a production environment (not a debug one)?

Yes.

Environment

Environment: "react": "16.8.3", "react-native": "^0.59.9", "react-native-snap-carousel": "^3.8.0",

Target Platform: iOS (12.2) & Higher

Expected Behavior

Carousel item should be loaded instantaneously and scrolling must be smooth.

Actual Behavior

Currently my Carousel modal window is displayed after 10 seconds and then data (9-10 items out of 2000) would be loaded after few seconds in which scrolling is not smooth either.

Reproducible Demo

(Paste the link to a Snack example in which the issue can be reproduced. Please follow the guidelines for providing a Minimal, Complete, and Verifiable example.)

Sorry, but I couldn't share my code on any public site as we've signed an NDA with the client.

Steps to Reproduce

So basically my problem is using Carousel item card with large data set, say - 2000.

I've a collection view of items on one of my views and then if user taps on any collection item then a modal view is displayed with details of that item in a card like UIVisualEffectView and that item card has dynamic buttons created in PureComponent of each card.

So my carousel component is like below:

<Carousel style = {styles.carouselContainer} ref = {(c) => { this._carousel = c; }} layout = {'default'} data = {this.state.entries} firstItem = {this.props.currentSelectedIndex} // initialNumToRender = {10} // windowSize = {10} onEndReachedThreshold = {0.01} renderItem = {item => this.renderItem(item)} sliderWidth = {Constants.iDeviceWidth} itemWidth = {globalFunction.wp(70) + (globalFunction.wp(5) * 4)} inactiveSlideScale = {0.95} enableMomentum = {true} decelerationRate = {'fast'} slideStyle = {styles.slideContentContainer} activeSlideAlignment = {'center'} scrollEndDragDebounceValue = {0} // enableSnap = {true} useScrollView = {false} removeClippedSubviews = {true} onLoadEnd = {this.carouselLoaded.bind(this)} onEndReached = {(item) => this.loadFurtherData(item)}/>

and my PureComponent for each item card to render is like below:

`renderItem ({item, index}) { let jsonData = JSON.parse(item.jsonRepresentation); let activeDataDetails = jsonData; let ingredientDetailsDynamicTabsArray = globalFunction.getDynamicTabsForIngredient(activeDataDetails, this.props.userData.accesses);

return <IngredientCard allIngredientsData = {this.state.entries} data = {item} ingredientIndex = {index} tabsArray = {ingredientDetailsDynamicTabsArray} userDetails = {this.props.userData} />;

}`

So, I want proper imaplemtation of my Carousel component so that my large data set (2000 items) would be displayed without any time lagging and horizontal scrolling of items must be smooth.

Indeed, everything is fine if I just load 20-30 items with useScrollView = {true} prop. But I understand that for large data set this can't be wise idea to use useScrollView = {true}.

Thanks in advance.

kirtishjain9 avatar Aug 23 '19 13:08 kirtishjain9

One thing that might help a bit, but probably won't make a massive difference would be to change this:

renderItem = {item => this.renderItem(item)}

To this:

renderItem = {this.renderItem}

Also try not passing in currentSelectedIndex into firstItem, e.g. don't change the firstItem after the initial render. Other than that a Snack would help a lot to see other reasons you might be having trouble.

thekevinbrown avatar Aug 30 '19 01:08 thekevinbrown

Hi @thekevinbrown,

Thanks for your reply. But I wonder if I don't use firstItem prop then how would I display item card which is being selected by user from the list.

Actually, I've a catalogue view (like Pinterest dashboard) to list all my data items and if user selects or taps on any data item cell then my Carousel modal view is displayed with all item cards but the first item must be the selected one. How could I achieve that?

Any suggestions would be appreciated.

Thanks in advance.

kirtishjain9 avatar Sep 03 '19 09:09 kirtishjain9

You can use the firstItem prop without changing it on state changes. That's what I'm suggesting.

However with a list as long as that you're also going to hit this: https://github.com/archriss/react-native-snap-carousel/issues/538

thekevinbrown avatar Sep 09 '19 00:09 thekevinbrown

@thekevinbrown Thanks for your reply. Yup..it worked for me for the firstItem.

But my initial problem is how should I load my large data set (upto 2000) with some complex UI item card for each carousel item without memory leaks.

For your reference, I'm attaching screen shots of my Item Card which should be displayed as each carousel item. There are some buttons - 'Overview', 'Marketing' and 'Medias'. and on clicking of each button different details are being displayed in below area.

Simulator Screen Shot - iPhone Xʀ - 2019-09-06 at 20 41 11

And if user scroll vertical in any item card then header of item card should be animated as shown in below screen shot

Simulator Screen Shot - iPhone Xʀ - 2019-09-06 at 20 56 18

Please suggest an efficient way to manage this type of carousel list with proper memory management.

Thanks in advance.

kirtishjain9 avatar Sep 10 '19 11:09 kirtishjain9

Are you seeing a specific memory leak? If so, the only way to really dig in and figure out what's going on is to see a reproduction case.

thekevinbrown avatar Sep 10 '19 12:09 thekevinbrown

@thekevinbrown Thanks for your prompt reply.

Leave the memory leaks as of now. Could you please suggest me how could I achieve a smooth Carousel list for my large Data Set (upto 2000 item cards) item cards as shown above.

kirtishjain9 avatar Sep 10 '19 12:09 kirtishjain9

https://github.com/archriss/react-native-snap-carousel/blob/master/doc/TIPS_AND_TRICKS.md#optimizing-performance

If you're having a problem not solved by those points please provide a reproduction so we can see what's happening.

thekevinbrown avatar Sep 10 '19 12:09 thekevinbrown

I too have this kind of issue. I have 200 items, with initial items of 10. But if I try to snapToItem(50), the 51st item is not yet rendered, so it will only snap on the 10th item instead.

Any diretctions is appreciated.

jeffreybello avatar Oct 16 '19 11:10 jeffreybello

@jeffreybello I had a similar problem but with a smaller volume of data, perhaps. What I did is reordered the array to put the item that I want to snap to, as the first item. This also meant that I had to re-arrange all items.

So if it's [1,2,3,4,5,6,7,8,9,10] and let's assume the initial render is 5, then to snap to the 9th item, I rearranged the array to be [9,10,1,2,3,4,5,6,7,8]. It seems a bit hacky to me and also works since I need a loop.

When I increased the initialNumToRender prop, it caused the UI to become glitchy and performance went down

Shivendra30 avatar Oct 21 '19 03:10 Shivendra30

I too have this kind of issue. I have 200 items, with initial items of 10. But if I try to snapToItem(50), the 51st item is not yet rendered, so it will only snap on the 10th item instead.

Any diretctions is appreciated.

@jeffreybello - if you're still having this issue try using the useScrollView prop, the underlying implementation is a virtualisedList which has built in lazy loading if you set useScrollView it will change the underlying implementation to a scrollview.

rossjohnsonMP avatar Nov 22 '19 14:11 rossjohnsonMP

Of course @rossjohnsonMP, if you use a scroll view then with 2000 complex items you'll probably run out of memory.

thekevinbrown avatar Dec 11 '19 01:12 thekevinbrown

If this library is base on Virtualized List, then "Windowing technique" would help

Or some tricks to improve Virtualized List perf: https://github.com/filipemerker/flatlist-performance-tips

luatnd avatar Nov 30 '20 08:11 luatnd

@kirtishjain9 Did you find a solution for your case?

edwardigates avatar Jan 26 '21 17:01 edwardigates

Sorry, please allow me to advertise for my open source library! ~ I think this library react-native-reanimated-carousel will solve your problem. It is a high performance and very simple component, complete with React-Native reanimated 2

dohooo avatar Oct 08 '21 05:10 dohooo

I too have this kind of issue. I have 200 items, with initial items of 10. But if I try to snapToItem(50), the 51st item is not yet rendered, so it will only snap on the 10th item instead. Any diretctions is appreciated.

@jeffreybello - if you're still having this issue try using the useScrollView prop, the underlying implementation is a virtualisedList which has built in lazy loading if you set useScrollView it will change the underlying implementation to a scrollview.

This approach works only when you have a small data set. When you have a large dataset (in my case over 200 items), you have to wait until all the items from the carousel will be rendered...

barbalata avatar Jan 21 '22 09:01 barbalata