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

More than 9 items in the data causes the Carousel to re-render all the items indefinitely #329

Open
amitassaraf opened this issue May 25, 2018 · 21 comments

Comments

@amitassaraf
Copy link

Is this a bug report or a feature request?

Bug report

Have you read the guidelines regarding bug report?

Yes.

Have you read the documentation in its entirety?

Yes.

Have you made sure that your issue hasn't already been reported/solved?

Yes.

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

I only have an iOS device so I am not sure.

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

Yes.

Have you made sure that it wasn't a React Native bug?

Yes

Have you been able to reproduce the bug in the provided example?

Yes

Environment

Environment:
React: 16.2.0
React native: 0.49.0
react-native-snap-carousel: 3.7.0

Target Platform:
iOS (8.0)

Steps to Reproduce

  1. Render a carousel with 9 items and console.log when the renderItem function is called.
  2. See that it only renders the items once, as it should.
  3. Then add a 10th item to the data array, and see how the renderItem methods is called indefinitely on every item.
<Carousel
                            data={[{a: '2'}, {a: '44'}, {a: '21'}, {a: '2'}, {a: '33'}, {a: '11'}, {a: '6'}, {a: '77'}, {a: '99'}, {a: '01'}]}
                            renderItem={({item, index}) => {
                                console.log('== RENDER ITEM == ' + index);
                                return <View />
                            }}
                            sliderWidth={Window.width}
                            itemWidth={Window.width}
                        />

Expected Behavior

I thought that I would only see render calls to the items that are visible and the rest would only be called ONCE they are visible.

Actual Behavior

The carousel constantly rerenders the items non stop.

image

@bd-arc
Copy link
Contributor

bd-arc commented May 25, 2018

Hi @amitassaraf,

This clearly looks like a React Native bug. First, have you made sure that your carousel is not a child of a ScrollView component? (see here for more info)

Then, does the issue persist with a newer version of React Native? The FlatList component upon which the plugin is based is known to be pretty buggy. The Facebook team sometimes fixes some of them; this is worth a try ;-)

@amitassaraf
Copy link
Author

amitassaraf commented May 25, 2018

@bd-arc Yes the Carousel is definitely not a direct child of ScrollView. React Navigation might be using a ScrollView somewhere, could this be the issue?

@bd-arc
Copy link
Contributor

bd-arc commented May 25, 2018

@amitassaraf I can't find the exact issue again, but I remember reading that when a FlatList is a child of a ScrollView (this includes FlatList, VirtualizedList and many plugins) it apparently renders all child components, even those currently off-screen.

This may have been fixed since then; that's why I recommend that you try with a newer version of React Native.

@amitassaraf
Copy link
Author

@bd-arc I upgraded to 0.55 with no luck. I will tomorrow try to use the carousel on a page outside the React Navigation cycle to see if it works. Maybe React Navigation uses a ScrollView of some sorts.

Even if this solves it I have no idea what to do, because I need React Navigation haha :) Maybe I'll look for a different navigation library :/

@amitassaraf
Copy link
Author

@bd-arc I have tested this in a sandbox environment and it still happens. Just use a carousel and add 10+ objects and it will infinitely render the items.

                <Carousel
                    data={[{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}, {id: 7}, {id: 8}, {id: 9}, {id: 10}, {id: 11}]}
                    enableSnap={true}
                    enableMomentum={true}
                    renderItem={({item, index}) => {
                        console.log('== RENDER ITEM ' + index);
                        return <Text>{item.id}</Text>
                    }}
                    keyExtractor={item => String(item.id)}
                    firstItem={1}
                    sliderWidth={Window.width}
                    itemWidth={Window.width * 0.85}
                />

@bd-arc
Copy link
Contributor

bd-arc commented May 28, 2018

@amitassaraf Can you try the same thing with a regular FlatList component and see if it behaves the same? We need to determine if this is a FlatList ou a Carousel bug.

Note that you can keep your data and renderItem props exactly the same.

@oidoug
Copy link

oidoug commented May 28, 2018

I'm using the carousel as a pager, loading large local images and I'm having the same problem, but in addition, some random itens do not show. It gets worse from page 10-12 ahead.

Using a PureComponent helped with unnecessary renders, but pages are still blank randomly.

I'm now trying to isolate the problem and will update if I find something useful. Thanks.

@bd-arc
Copy link
Contributor

bd-arc commented May 28, 2018

@douglaslondrina I'm definitely interested in your findings. If this is an issue with the plugin itself, I'll have to work on a fix; if this has to do with the FlatList, let's hope we can hack our way out.

@amitassaraf
Copy link
Author

@bd-arc I'll check tomorrow. My hack around this was to check inside the renderItem method if the index is the currentIndex +- 1 and only then render my element, otherwise return null :/

@oidoug
Copy link

oidoug commented May 30, 2018

The problem really seams to be with FlatList, I tried it isolated and still got weird blank pages on android real devices (on emulator it works ok). I'm on a tight schedule and am working now with https://github.com/Flipkart/recyclerlistview lib, but I'll investigate it further as soon as possible.

@UdaraJay
Copy link

UdaraJay commented Jul 8, 2018

Any update on this? Ran into the same issue...

1 similar comment
@sridhard
Copy link

Any update on this? Ran into the same issue...

@sridhard
Copy link

This is same as #349 ..Please check

@UdaraJay
Copy link

I had the same issue and at-least in my case it turned out to be the case the issue was the content in the carousel component - the items were re-rendering continuously... which slowed down the carousel and made it very glitchy.

So I'd suggest taking a second look at the content you put in the carousel.

@roks0n
Copy link

roks0n commented Jul 11, 2019

+1 on what @UdaraJay is saying. Had the same issue but was able to fix it after changing the components I've was rendering in renderItem from Component to PureComponent.

@bimix
Copy link

bimix commented Oct 19, 2019

has this been fixed yet? Any updates?

@bimix
Copy link

bimix commented Oct 19, 2019

I have found a fix for this issue, here I will post my carousel implementation:```
` <Carousel
ref={c => this._slider1Ref = c}
data={this.state.All}
renderItem={this._renderItemWithParallax.bind(this)}
//enableMomentum={true}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
hasParallaxImages={true}
firstItem={SLIDER_1_FIRST_ITEM}
inactiveSlideScale={0.94}
inactiveSlideOpacity={0.7}
//inactiveSlideShift={20}
containerCustomStyle={styles.slider}
contentContainerCustomStyle={styles.sliderContentContainer}
loop={false}
loopClonesPerSide={2}
autoplay={false}
enableSnap={false}

                maxToRenderPerBatch={8}
                initialNumToRender={4}
                onEndReached={this.onEndReached.bind(this)}
                onEndReachedThreshold={0.5}
                onMomentumScrollBegin={() => { this.onEndReachedCalledDuringMomentum = false; }}

                // onEndReached = ({ distanceFromEnd }) => {
                //     if(!this.onEndReachedCalledDuringMomentum){
                //         this.fetchData();
                //         this.onEndReachedCalledDuringMomentum = true;
                //     }
                // }
                removeClippedSubviews={true}
                // autoplayDelay={500}
                // autoplayInterval={3000}
                onSnapToItem={(index) => this.setState({ slider1ActiveSlide: index })}
            >`

` momentumExample(number, title) {
return (

{"Te gjitha restaurantet"}
{title}
<Carousel
data={this.state.All}
renderItem={this._renderItem.bind(this)}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
inactiveSlideScale={0.95}
inactiveSlideOpacity={1}
enableMomentum={true}
loop={false}
activeSlideAlignment={'start'}
hasParallaxImages={true}
containerCustomStyle={styles.slider}
contentContainerCustomStyle={styles.sliderContentContainer}
activeAnimationType={'spring'}
activeAnimationOptions={{
friction: 4,
tension: 40
}}
/>

);
}

onEndReached = ({ distanceFromEnd }) => {
    if (!this.onEndReachedCalledDuringMomentum) {
        this.state.All;
        this.onEndReachedCalledDuringMomentum = true;
    }
}

`

@kasiri182
Copy link

Anyone want to solve this problem?

@donni106
Copy link

donni106 commented Aug 25, 2020

My renderItem also gets called randomly and continuously, when my data exceeds a certain length. What is that more than 9 items? How is that number of items effecting the code? What can cause the re-renders?

@SomnathKadam
Copy link

is any one found solution?

@dohooo

This comment was marked as spam.

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

No branches or pull requests