meliorence / react-native-snap-carousel

Swiper/carousel component for React Native featuring previews, multiple layouts, parallax images, performant handling of huge numbers of items, and more. Compatible with Android & iOS.
BSD 3-Clause "New" or "Revised" License
10.32k stars 2.28k forks source link

snapToItem doesn't change the current index "quick enough" #581

Open kevinvugts opened 4 years ago

kevinvugts commented 4 years ago

Bug Report

This is a bug report

Have you followed the required steps before opening a bug report?

(Check the step you've followed - put an x character between the square brackets ([]).)

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

Yes

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

Only tested on Ios

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

No

Environment

Environment:

React Native: https://github.com/expo/react-native/archive/sdk-34.0.1.tar.gz React-native-snap-carousel: ^3.7.5 Target platform: iOS (12.0) -> EXPO

(Write your answer here.)

Expected Behavior

When programmatically snapToItem it will change the current index in the callback of the renderItem function with the correct value.

(Write what you thought would happen.)

See above.

When programmatically changing the snapToItem proving an index doesn't change the currentIndex or doesn't change the currentIndex quick enough in the carousel. So when the render function is being called I am receiving an old current Index which is crashing my existing code.

Reproducible Demo

  renderFiveHundredFilter = ({item, index}) => {
    console.log("CURRENT_INDEX", this._carousel.currentIndex);

     ^^ this._carousel.currentIndex won't change when an item is pressed. It will remain on 0

    return (
      <Text onPress={() => {
        this._carousel.snapToItem(index);
        this.onPrivilegesRangeChange("click", index)
      }
    } key={`abc_${index}`} style={{color: this._carousel.currentIndex === index ? "gold" : "white", fontFamily: Fonts.heavy, fontSize: Fonts.small}}>{item.name}</Text>
    )
  }

Steps to Reproduce

  1. Create a simple Carousel
  2. Change to a snap item programmatically using snapToItem callback function
  3. See if the currentIndex of the carousel is being received in the render function with the correct result.
kevinvugts commented 4 years ago

When adding the following properties it started to work:

activeSlideOffset={2}
enableMomentum={true}

Can someone please explain why it works now? Someone else also appears to have this problem: https://github.com/archriss/react-native-snap-carousel/issues/541#issuecomment-514165668

prasadkesarkar commented 4 years ago

Is it working with Android?

kevinvugts commented 4 years ago

Is it working with Android?

On Android the whole snapToItem is not working.

efthimispegas commented 4 years ago

I use it with react-navigation and I want to programmatically snap to item on screen focus. The way I try to do this is by attaching an event listener to navigation: (This is the basic code behind my implemenation)

 ...
this._carousel = null
...
componentDidMount() {
  ...
  this.willFocus = this.props.navigation.addListener('willFocus', async () => {
  this._carousel.snapToItem(0)
})
}

...

render() {
  <Carousel
    ...
    ref={c => { this._carousel = c }}
  />
}`

. The behavior I get is this: I manage to programmatically snap to the first item of the carousel but a moment later I get snapped back to the carousel's last state. I also tried attaching a willBlur listener trying to apply the same action but got nothing there too.

dohooo commented 2 years ago

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