react-native-snap-carousel: firstItem not working

Hey, I’m having an issue with setting firstItem. Most of the time, the wrong item is selected. We are using a function which returns the children, so we got something like this:

<Carousel
                    ref={'covers'}
                    sliderWidth={viewportWidth}
                    itemWidth={240}
                    inactiveSlideScale={0.9}
                    inactiveSlideOpacity={0.6}
                    showsHorizontalScrollIndicator={false}
                    snapOnAndroid={true}
                    removeClippedSubviews={false}
                    onSnapToItem={this.onSnap}
                    firstItem={8}
                >
                    {this.getCovers()}
</Carousel>

In our case, the 8th item wasn’t selected when the component mounts. If we do something like this:

componentDidMount() {
    setTimeout(() => { this.refs.covers.snapToItem(8,false); },500);
}

…the correct item is selected. Are there any issues when generating the childrens via function?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 4
  • Comments: 16 (8 by maintainers)

Most upvoted comments

 I had same problem i add initialNumToRender={100} so Carousel working fine for first . 100 items 
        <Carousel
          ref={(c) => { this._carousel = c; }}
          initialNumToRender={100}
          data={this.state.picture}
          firstItem={this.state.index}
          renderItem={this._renderItem}
         sliderWidth={500}
          itemWidth={500}
          
          //onSnapToItem={(index) => this.setState({ activeSlide: index }) }
        />
    );
}

}

I just had similar issue where the carousel has long list (eg. 90 items) and set the firstItem into high number will always select the 12th item. It turns out I have to add getItemLayout in order for FlatList to figure out how long the list will be.

<Carousel
...
getItemLayout={(data, index) => ({offset: viewportWidth * index, length: viewportWidth, index})}
...
/>

I hope this helps someone else related to firstItem issue.

@juanamd Unfortunately, this is definitely a FlatList bug, which is confirmed by the fact that everything works properly when setting useScrollView to true.

I’ll copy-paste my comment to a similar issue as this might still help you.

I’ve just had an idea and tried overriding the default initialNumToRender by setting it to 30. Result: it works! This means that the issue is, as I feared, a FlatList one and that I have no control over this behavior. It seems like the FlatList component is not able to properly keep track of the items that are not in the currently rendered batch…

I see three options at this point:

  • Set useScrollView to true. Note that you will loose all FlatList optimizations by doing that.
  • Play with the following FlatList props until you find something that suits your needs: initialNumToRender, maxToRenderPerBatch, windowSize and updateCellsBatchingPeriod.
  • Pray that the Facebook team will, some day, fix all those ridiculous issues
 I had same problem i add initialNumToRender={100} so Carousel working fine for first . 100 items 
        <Carousel
          ref={(c) => { this._carousel = c; }}
          initialNumToRender={100}
          data={this.state.picture}
          firstItem={this.state.index}
          renderItem={this._renderItem}
         sliderWidth={500}
          itemWidth={500}
          
          //onSnapToItem={(index) => this.setState({ activeSlide: index }) }
        />
    );
}

}

I’m wondering why firstItem after some index is not showing related index data from array. I use your way which adding initial number to array length. Solving my firstItem thought

Thanks @balwinder4264 I used your solution with a slight tweak, I set initialNumToRender={this.state.picture.length}, in my case I sometimes had a list with only a few items, other times I had a long list

Hey @dnish,

You shouldn’t have any issue when returning children from a custom method (in fact, that’s the way we’re doing it). Still, there might be a problem if your children are generated asynchronously. This is supposed to be handled, but you might have uncovered some dirt 😃

Could you share your method getCovers() so I can try to reproduce your issue? Could you also try this workaround and let me know if that works for you?