This is not a bug but the experience is poor with the current behaviour.
After the animation is done the new index is updated.
Similar issue: https://github.com/react-native-community/react-native-tab-view/issues/463
When we actually know what the next index is, it should be updated.
https://snack.expo.io/Syl8kbtvV
Haven't looked in the Pager component so much but why not do the call([this._index], ([value])) in the Pager component when the animation starts instead of finished?
I tried to do the code below and works well. I needed to this._currentIndexValue = value as well otherwise it would jump 2 screens. I believe that you have a reason for doing it after the animation is done but I would like to know why. I can do a PR if I actually know the reason behind it.
cond(clockRunning(this._clock), NOOP, [
// Animation wasn't running before
// Set the initial values and start the clock
set(toValue, multiply(index, this._layoutWidth, DIRECTION_RIGHT)),
set(frameTime, 0),
set(state.time, 0),
set(state.finished, FALSE),
set(this._index, index),
startClock(this._clock),
call([this._index], ([value]) => {
// If the index changed, and previous animation has finished, update state
this._currentIndexValue = value
this.props.onIndexChange(value)
// Without this check, the pager can go to an infinite update <-> animate loop for sync updates
if (value !== this.props.navigationState.index) {
this._pendingIndexValue = value
// Force componentDidUpdate to fire, whether user does a setState or not
// This allows us to detect when the user drops the update and revert back
// It's necessary to make sure that the state stays in sync
this.forceUpdate()
}
}),
]),
| software | version
| ---------------------------- | -------
| ios or android | both
| react-native | 0.58.3
| react-native-tab-view | 2.0.2
| react-native-gesture-handler | 1.1.0
| react-native-reanimated | 1.0.0-alpha.12
| node | 10
| npm or yarn | [email protected]
I got this experience too, especially after upgraded the lib to v2.0.2 as v1.3.2 is buggy on react-native v0.59 (_the tab button press is not working anymore_), i won't back to the older version. Any idea @satya164 ?
Would also like to have the index updated as soon as possible or at least before the animation is done.
The reason onIndexChange is fired after the animation is done is because updating the state in the middle of the animation can cause frame drops. It's less noticeable with the new native animations, but depending on how expensive the setState is, it can be noticeable.
You can check the scrollable tab example in your PR and see how bad the frame drop looks on the scrollable tabs. The examples are very simple and I have a high-end pixel device, it'll be worse on lower-end phones and more complex examples.
This is not new behavior. We did similar in 1.x as well: https://github.com/react-native-community/react-native-tab-view/blob/1.0/src/PagerScroll.js#L106
Why do you need the state to update in the middle of the transition? Maybe you can open a new issue regarding your use case?
We have lottie animations and what to play/pause them when a tab is active or not. When we have a delay for 1 sec the app feels quite slow. Lottie animations on android makes the app drop frames when they are active and that's why we want to play/pause.
We haven't notice any performance issues when swiping between tabs at least and we have quite heavy tabs.
What if I do so this is optional as a prop. Would you consider merging this? Or do you have a better approach for doing this?
Thanks!
Will passing the next route to onSwipeEnd work for you? It'll let you know when we're ready to switch the tabs without triggering a setState for everyone. Another option is to add something like a focus event like react-navigation has.
What if I do so this is optional as a prop.
I won't add this behavior as a prop because it's a fundamental behavior and having 2 separate behaviors will make it harder for me to maintain and ensure both behaviors keep working properly (reanimated is not the easiest to work with).
OnIndexChange mean 'didFocus'
but OnSwipeEnd has no argument which direction or nextIndex
I want to know
direction or nextIndex in OnSwipeEnd,
Or
earlier than OnIndexChange (not animation finished timing)
How can I do?
@satya164 at lease default ripple should not delay the setting index
I want to add routes dynamically (active current day and infinity prev and next days), so in OnSwipeEnd I need to know nextIndex to add new route and remove unused.
Addressed in 116dc0b3823637fd3344d1cfb43bbd2e0541b8fe
Most helpful comment
@satya164 at lease default ripple should not delay the setting index