react-navigation / react-navigation/react-navigation
Allow per-jump animation control for TabView / Material Top Tabs
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 24.5k
- Forks
- 5.1k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 18
Description
Current behavior
react-native-tab-view exposes animationEnabled as a global boolean. This is enough to always animate or never animate tab changes, but it doesn't let a custom tab bar decide that a specific jumpTo call should skip animation.
The underlying native primitive, react-native-pager-view, already supports both behaviors with setPage(index) and setPageWithoutAnimation(index). PagerViewAdapter currently selects between them based on the global animationEnabled prop.
This comes up in apps with heavy top-level tabs and a custom tab bar. A normal tab press should still animate, but if the user rapidly presses between tabs, the second/third press should be able to cancel or skip the in-flight animation and jump immediately to the requested tab. The current public API doesn't provide a way to do that without either:
- setting
animationEnabled: falsefor all tab presses/programmatic changes, or - patching
PagerViewAdapterinternally to usesetPageWithoutAnimationconditionally.
Related prior issues:
- https://github.com/react-navigation/react-navigation/issues/8273
- https://github.com/satya164/react-native-tab-view/issues/1371
- https://github.com/satya164/react-native-tab-view/pull/1388
Issue #1371 / PR #1388 solved the coarse version of this by adding animationEnabled. This request is for the next layer: per-jump animation policy.
Expected behavior
Would maintainers be open to a patch that allows jumpTo to opt out of animation for a specific tab change, while preserving current behavior by default?
One possible API shape:
type JumpToOptions = {
animated?: boolean;
};
type SceneRendererProps = {
// Backwards compatible: existing `jumpTo(key)` calls keep using `animationEnabled`.
jumpTo: (key: string, options?: JumpToOptions) => void;
};
Then a custom tab bar could do something like:
const isRapidPress = Date.now() - lastTabPressAt.current < 250;
lastTabPressAt.current = Date.now();
jumpTo(route.key, { animated: !isRapidPress });
Internally, PagerViewAdapter could choose between setPage(index) and setPageWithoutAnimation(index) based on options?.animated ?? animationEnabled. The web / pan responder adapter could use the same optional argument to choose whether to animate the jump.
This would avoid app-level patches while keeping the existing global animationEnabled prop as the default policy.
I am happy to put together a PR if this API direction seems acceptable. If maintainers would prefer a different shape, such as an animationEnabled callback or a shouldAnimateJump(fromIndex, toIndex) prop, I'm glad to adapt before implementing.
Reproduction
https://github.com/tian000/react-navigation-tabview-rapid-jump-repro
This is a minimal Expo repro using the latest @react-navigation/native, @react-navigation/material-top-tabs, and react-native-tab-view versions currently published on npm.
The repro renders two sections:
react-native-tab-view: rapid tab presses are detected, but the custom tab bar can only calljumpTo(route.key). The desiredjumpTo(route.key, { animated: !isRapidPress })API is shown in a code comment.- direct
react-native-pager-view: rapid tab presses callsetPageWithoutAnimation; normal tab presses callsetPage, demonstrating that the lower-level primitive supports the behavior.
Run:
npm install
npm run android
or:
npm install
npm run ios
Then rapidly press Home, Trade, and Explore in both sections.
Platform
- Android
- iOS
- Web
- Windows
- MacOS
Packages
- '@react-navigation/material-top-tabs'
- 'react-native-tab-view'
Environment
Verified with the repro app:
| package | version |
|---|---|
| @react-navigation/native | 7.2.2 |
| @react-navigation/material-top-tabs | 7.4.24 |
| react-native-tab-view | 4.3.0 |
| react-native-pager-view | 6.9.1 |
| react-native | 0.81.5 |
| expo | 54.0.33 |
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review the PagerViewAdapter and the web/pan responder adapter entry points described in the issue, then run the linked rapid-jump repro with npm install and the Android or iOS command. Define the API direction with maintainers first; done should preserve animationEnabled as the default while allowing an individual jump to select animated or non-animated behavior across the relevant adapters.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react-native, typescript
- Domain
- frontend, mobile
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100