react-native-screens
react-native-screens copied to clipboard
bug with @react-navigation/bottom-tabs - initial jumping and flickering
Description
When I'm using @react-navigation/bottom-tabs
with the native stack navigator, the header jumps on android and sometimes flickers on iOS on tab change (on the first render only). But it doesn't happen if I use the JS stack navigator.
I wrapped NavigationContainer
with SafeAreaProvider
like this:
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<NavigationContainer>
<RootStack />
</NavigationContainer>
</SafeAreaProvider>
I also patched react-navigation bottoms tabs with this PR applied by @WoLewicki react-navigation/react-navigation#9772
If I remove initialWindowMetrics
jump on Android is gone, but on iOS, the header is still flickering.
it maybe related to this issue
Screenshots
https://user-images.githubusercontent.com/86000012/150523094-f45c0d6d-b059-45f1-aaae-2f7441b1f0a3.mov
https://user-images.githubusercontent.com/86000012/150523458-835419ca-5f86-4762-a677-6060101566a1.mov
Steps To Reproduce
- Open app.
- Click on Tab2.
- See the position of the header.
Expected behavior
the header should not jump on android and flicker on iOS(on initial render).
Actual behavior
on initial render, header jumps on Android and flickers on iOS
Reproduction
reproduction repo:
https://github.com/IvanIhnatsiuk/native-stack-bottom-jump
Platform
- [x] iOS
- [x] Android
- [ ] Web
- [ ] Windows
- [ ] tvOS
Workflow
- [ ] Managed workflow
- [x] Bare workflow
Package versions
package | version |
---|---|
react-native | 0.66.4 |
@react-navigation/native | 6.0.9 |
@react-navigation/native-stack | 6.2.5 |
react-native-screens | 3.10.2 |
react-native-safe-area-context | 3.3.2 |
react-native-gesture-handler | 2.2.0 |
react-native-reanimated | 2.3.1 |
@react-navigation/bottom-tabs | 6.0.9 |
Can you explain why this SafeAreaProvider
at the top is needed?
@WoLewicki Yes, sure.
We use the insets from SafeAreaProvider
in our project, if you remove it, the flickering problem is still on iOS.
I was asking since it is already applied in native-stack
: https://github.com/react-navigation/react-navigation/blob/e9c690450068d29a2ce62004992ad75d626ca0c2/packages/native-stack/src/views/NativeStackView.native.tsx#L322 so it may be causing some problems with layout. As for the flickering, does the whole content flicker or is it just the header? It is not visible when you have white background 😅
Sorry, in official react-navigation they suggest to wrap entire app in a SafeAreProvider
: https://reactnavigation.org/docs/handling-safe-area/
But they also have SafeAreaPrivederCompat
: https://github.com/react-navigation/react-navigation/blob/main/packages/stack/src/views/Stack/StackView.tsx#L430
And Js stacks are not flickering/jumping 🤔 Am I doing something wrong?
Video with non-white color is attached:
https://user-images.githubusercontent.com/86000012/150536292-81ba476e-a9a6-435b-8103-cf4739ce21bd.mov
@owinter86
Thank you for your research of the problem!
I tried the solution of wrapping each tab element in SafeAreaProvider
.
Unfortunately, it doesn't solve the problem with flickering on iOS 😞 .
Also, it doesn't always help on android, sometimes the screen jumps on the initial render 😞 .
I think the author of this issue also tried it because he described it in the description.
Also, I didn't find any information about wrapping each tab element in the documentation. I think that the application should have only one SafeAreaProvider
and it should already contain all the metrics that the native Stack and JS Stack use.
Anyway, It might be a good vector to find a problem, Thanks!
I'm also expecting this issue on Android.
My content jumps, flickering and hides behind the header. Do you have any updates here?
@WoLewicki are u suggesting that when using the native-stack
there is no need to wrapping your entire app in a SafeAreaProvider
?
@WoLewicki I also experience the iOS flicker when navigating for the first time into a tab. I can tell that:
- It happens from any version after
3.3.0
. In3.3.0
, it works - It only happens when your tab is a stack like here: https://github.com/IvanIhnatsiuk/native-stack-bottom-jump/blob/master/src/navigation/BottomTabNav/index.tsx#L10. If the stack is just a normal view, it does not flicker
- You need to have some content inside your tab. Not just a text or empty content in order for this to happen
I can also confirm this issue happens after this PR https://github.com/software-mansion/react-native-screens/pull/986.
@ferrannp I am getting flickering when my tab navigator is nested within a stack navigator as well, and for me it only happens when the component rerenders very shortly after the component initially mounts. If no rerender happens quickly the problem does not occur
Reverted to 3.3.0
as you said, and it fixed the issue.
Is anyone working on this? Or should I just assume I need to default to version 3.3.0
moving forward to avoid this sort of thing?
@iway1 when you say reverting to 3.3.0
you mean react-native-screens
?
This is what I'm running right now and experiencing jumping on first render:
"@react-navigation/bottom-tabs": "^6.3.1",
"@react-navigation/native": "^6.0.10",
"@react-navigation/stack": "^6.2.1",
"react-native-gesture-handler": "^2.4.2",
"react-native-safe-area-context": "^4.3.1",
"react-native-screens": "^3.13.1",
Yes, unfortunately you have to downgrade react-native-screens to 3.3.0 to remove the white flash between tab switches on ios. This doesn't always happen, only when the screen loads for the first time. it seems that the native stack navigator doesn't play well with the bottom tab navigator.
@ferrannp described exactly what caused the flicker.
On android the combination of native stack navigator and bottom tab navigator causes a short jump during initial load.
The solution to this is to add initial safe area metrics to 0:
return <SafeAreaProvider initialMetrics={{
insets: {
top: 0,
right: 0,
bottom: 0,
left: 0
}
}}>
<MyApp />
</ SafeAreaProvider>
And wrap your tab navigator with SafeAreaView:
return <SafeAreaView style={{ flex: 1}} >
<Tab.Navigator>
{myAwesomeTabs}
</Tab.Navigator>
</SafeAreaView>
@mordechaim no, that's not the solution, it jumps anyway and creates unnecessary space in the safe areas, especially on ios
@mirzalikic I’ve posted a solution on a similar issue. Stubbing SafeAreaView
with a custom implementation using the useSafeAreaInsets
measurements resolved my problems:
https://github.com/software-mansion/react-native-screens/issues/1251#issuecomment-1154533585
Fixed this by swapping <SafeAreaView />
with useSafeAreaInsets()
<View style={[styles.container, { paddingTop: Math.max(insets.top, 16) }]} {...otherProps}>
@sjransom Thanks, your solution works! no more jumping and flickering
replaced <SafeAreaView>
on Tab Screens to <View>
with the insets
import { useSafeAreaInsets } from 'react-native-safe-area-context';
function HookComponent() {
const insets = useSafeAreaInsets();
return <View style={{ paddingTop: Math.max(insets.top, 16) }}> ... </View>
}
@SashaGo3 is there any chance you can provide a full example of something that works? I'm trying to use your suggestion but I'm still getting the glitching effect :(
Still having the issue aswell on android, removed all SafeAreaViews and replaced with View + insets but the problem persists. Could anyone post a full example to see if I'm doing anything wrong?/Alternate solutions?
@ystefanov6 check my comment on #1251 to see if that helps you at all
@ystefanov6 check my comment on #1251 to see if that helps you at all
Thanks for this. Unfortunately I'm using expo and the latest supported version of screens for sdk 45.0 is 3.11.1, upgrading anyway doesn't seem to fix it either. Don't know what else to try at this point.
same issue on react-native-screens: "3.9.0"
downgrade to 3.3.0
not helps
android platform
I finally managed to fix it in my case by replacing materialBottomTabs to just the bare bottomTabs, it lacks nice animations but flicker is gone. Apparently it's a known issue with materialBottomTabs and stack nav when they're nested together. Hope this helps someone. If you're looking for a pre-built animated component for the navbar I suggest https://www.npmjs.com/package/rn-wave-bottom-bar.
@mirzalikic solution worked for me, just downgrade to [email protected]
Same issue with [email protected]
Downgrading to 3.3.0 resolved that problem. However, it messed up other things in the app so I upgraded back to 3.18.0.
Doing this fixed the <SafeAreaView/> flicker on all screens except the stacks that are used in bottom tab stack.
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const Component = () => {
const insets = useSafeAreaInsets();
return <View style={{ marginTop: insets.top }}> ... </View>
}
Finally the solution:~
Don't use SafeAreaView instead use the hook useSafeAreaInsets() If you use Bottom Tab Navigator createBottomTabNavigator(). Don't pass a Stack in component prop. Pass a View. In some cases you might not want or be able to do that, if that's the case downgrade to [email protected] is the only solution I found.
The solution to this is to add initial safe area metrics to 0:
return <SafeAreaProvider initialMetrics={{ insets: { top: 0, right: 0, bottom: 0, left: 0 } }}> <MyApp /> </ SafeAreaProvider>
And wrap your tab navigator with SafeAreaView:
return <SafeAreaView style={{ flex: 1}} > <Tab.Navigator> {myAwesomeTabs} </Tab.Navigator> </SafeAreaView>
Wrapping Tab.Navigator with SafeAreaView worked for me! 🙏
Can anyone create a repo with the solution suggested? I tried wrapping SafeAreaView and SafeAreaProvider it was still flickering for me. @banjolina-jolie ?
I still facing same problem, there is any example to follow