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

initialScrollIndex does not work all the time #615

Open
5 tasks done
ALexandreM75013 opened this issue Nov 2, 2019 · 15 comments
Open
5 tasks done

initialScrollIndex does not work all the time #615

ALexandreM75013 opened this issue Nov 2, 2019 · 15 comments
Labels

Comments

@ALexandreM75013
Copy link

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

This is a bug report.

The possibility to be able to use the props getItemLayout & initialScrollIndex (which I believe is a very good idea because of the optimisation of getItemLayout) does not work all the time.

Sometimes, the initialScrollIndex() does not work and renders the first item. The bug does not appear all the time, sometimes it works perfectly and sometimes it doesn't. I have tried with a normal Flatlist in which all the items are the size of the screen to be sure if it is not a bug from Flatlist but it never failed. So the problem comes from SnapCarousel.

To explain what I am doing, I use the snap-carousel to show pictures fullscreen and the user can swipe between the pictures. The first picture rendered depends on what picture the user pressed before in a kind of gallery. I always tried with the last item of the list (9 items), and sometimes it show me indeed the last item and sometimes the first item. I do exactly the same actions each time.

I tried also with initialNumToRender() with a value of the index of the first item to show (it was necessary with firstIndex prop) but it does not change anything.

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, because it works perfectly with a normal Flatlist all the time.

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

Tried on two android devices : android 8.1 android 9 => both has the problem

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

I tried without the debug on. The problem appears.

Environment

Environment:
React: 16.8.6
React native: 0.60.5
react-native-snap-carousel: 3.8.4

Target Platform:
Android (8.0 / 0.9)
iOS (latest)

Expected Behavior

I expect that initialScrollIndex() show me the index I passed

Actual Behavior

initialScrollIndex() does not show me all the time the index passed and show me the first item of the list.

Reproducible Demo

I will try to post a reproductible demo. But maybe some other people has encountered the same problem so this post is for that.

Steps to Reproduce

Code used:

getItemLayout = (data, index) => {
    return { length: SCREEN_WIDTH, offset: SCREEN_WIDTH * index, index };
}

render() {
    <Carousel
      ref={this.refCarousel}
      data={this.state.render_list}
      renderItem={this.renderItem}
      sliderWidth={SCREEN_WIDTH}
      itemWidth={SCREEN_WIDTH}
      containerCustomStyle={[styles.CarouselStyle]}
      onBeforeSnapToItem={this.onBeforeSnapToItem}
      initialScrollIndex={this.state.initial_index}
      contentContainerCustomStyle={styles.contentContainerCustomStyle}
      removeClippedSubviews
      windowSize={10}
      scrollEventThrottle={16}
      getItemLayout={this.getItemLayout}
      keyExtractor={this.keyExtractor}
      shouldOptimizeUpdates={false}
   />
);
@bd-arc bd-arc added the bug label Nov 4, 2019
@bd-arc
Copy link
Contributor

bd-arc commented Nov 4, 2019

Hi @AlexandreMaistret,

This is a very valid concern indeed! The thing that troubles me the most is the randomness of it — no developer loves that...

Off the top of my head, I think that we might need to connect initialScrollIndex and firstItem. Is it working if you set firstItem to this.state.initial_index?

@ALexandreM75013
Copy link
Author

Hi @bd-arc !

Yes it is totally random, I don't know why.

I have several SnapCarousels in my app an all of them has the same problem.

Before 3.8.4 I was using indeed firstItem and it was working but I don't want to use is it because of the Android bug in which you need to set initialNumToRender and with firstItem there is also a small delay before the good item is rendered (really little delay but noticeable).

@cesar3030
Copy link

Same problem as well. I downgraded to 3.8.1 and it seems to work properly...

@jehartzog
Copy link

We found that this was due to a number of factors, but we could easily reproduce this by sending a new list of data into the carousel while it was in the process of an animation to some index.

I went digging deep into the Carousel.js and realized that it was keeping it's internal state up to date for the most part, but it was starting animations based on the old state which were making the carousel end up selected on an image did not match the currently selected index.

I did not dive deep into how this was happening, but I added a short method which is called every time we update the selected index and forces the Carousel to try to kill animations which may be going on and force it to keep the selected index.

The change isn't really worth of a PR at this point, but I wanted to bring up the solution we created just in case somebody can use it, maybe help explain why it's happening, and I wouldn't mind working on a PR to help merge into this repor.

Here is the function we added, and here is how we use it:

componentDidUpdate(): {
    const { selectedContactIndex } = this.getSelected();
    this.carousel._MM_hackSetActive(selectedContactIndex); // We use a ref we set to the Carousel earlier
}

Lazy, but it works, and we no longer end up with a Carousel selected image out of sync with our desired selectedIndex

@nohharri
Copy link

Hi @jehartzog, great solution! I had a very specific situation where our app is hiding and showing certain items in the carousel so this met my specific case. If anyone else is using this, remember to add the bindings in the constructor:

// Carousel constructor
constructor(props) {
    // ...
    this._MM_hackSetActive = this._MM_hackSetActive.bind(this);
}

@bd-arc
Copy link
Contributor

bd-arc commented Nov 27, 2019

@jehartzog Thanks for sharing your hack!

I would merge a PR that addresses the root of the issue without a second thought. If you feel up for some more digging, let me know ;-)

@stepupithubapp
Copy link

stepupithubapp commented Dec 4, 2019

componentDidUpdate() {
const selectedContactIndex = id;
this.carousel._MM_hackSetActive(selectedContactIndex); // We use a ref we set to the Carousel earlier
}

@jehartzog
i do same like you have described but it gives me error
TypeError: Cannot read property '_MM_hackSetActive' f undefined

@jehartzog
Copy link

@stepupithubapp You need to set the ref on your carousel:

<Carousel
  ref={(c) => {
    this.carousel = c;
  }}

@Rishabh-Streak
Copy link

@stepupithubapp You need to set the ref on your carousel:

<Carousel
  ref={(c) => {
    this.carousel = c;
  }}

Facing same issue & Seems setting ref doesn't help for my case. (Not sure how it is related also)

@omrip2
Copy link

omrip2 commented Jul 12, 2020

Any solution for this? I also having this issue

@martinlockett
Copy link

Any solution for this? I also having this issue

I used
removeClippedSubviews={false}

Maybe not a solution but a work around if it suits you

@omrip2
Copy link

omrip2 commented Jul 13, 2020

@martinlockett Be careful with that
image

@whalemare
Copy link

Hack, but working.

  useEffect(() => {
    const timeout = setTimeout(() => {
      carouselRef?.current?.snapToItem(selectedIndex)
    }, 60)
    return () => clearTimeout(timeout)
  }, [carouselRef?.current, selectedIndex])

@martinlockett
Copy link

@martinlockett Be careful with that
image

Thanks @omrip2

@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
Labels
Projects
None yet
Development

No branches or pull requests