react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

[iOS] bug with @react-navigation/bottom-tabs - initial jumping

Open hirbod opened this issue 2 years ago ā€¢ 30 comments

Description

When using @react-navigation/bottom-tabs with RNS, the content jumps on tab change (one the first render only). I made sure I've tested this plenty of times.

The bug does not occur if I import

import { createStackNavigator } from '@react-navigation/stack';

but with

import { createNativeStackNavigator } from '@react-navigation/native-stack';

My whole is wrapped with SafeAreaProvider from react-native-safe-area-context like so:

import {
  SafeAreaProvider,
  initialWindowMetrics
} from 'react-native-safe-area-context';
        <SafeAreaProvider initialMetrics={initialWindowMetrics}>
            <Navigator theme={combinedTheme} />
        </SafeAreaProvider>

I also tried to test it without initialMetrics and also used SafeAreaView(from react-native-safe-area-context and react-native), but it still jumped for me.

I also patched react-navigation bottoms tabs with this PR applied by @WoLewicki https://github.com/react-navigation/react-navigation/pull/9772

But the jump still occur. Also made sure to disable/enable freeze etc. I couldn't manage to prevent the initial jumping. See my video attached.

Screenshots

I created a dead simple preview, see my Video below. Please watch the in the center. https://streamable.com/i7upqv

Expected behavior

Should not jump on initial render

Actual behavior

It jumps on initial render and it does look weird

Reproduction

Happens on iOS, snack not helping here.

Platform

  • [X] iOS
  • [ ] Android
  • [ ] Web
  • [ ] Windows
  • [ ] tvOS

Workflow

  • [X] Managed workflow
  • [X] Bare workflow

Package versions

package version
react-native 0.64.3
@react-navigation/native 6.0.6
@react-navigation/native-stack 6.2.5
react-native-screens 3.10.1
react-native-safe-area-context 3.3.2
react-native-gesture-handler 2.1.0
react-native-reanimated 2.3.1
expo 44.0.3
  Expo CLI 5.0.3 environment info:
    System:
      OS: macOS 11.6.1
      Shell: 5.8 - /bin/zsh
    Binaries:
      Node: 14.18.2 - /usr/local/opt/node@14/bin/node
      Yarn: 1.22.17 - /usr/local/bin/yarn
      npm: 6.14.15 - /usr/local/opt/node@14/bin/npm
      Watchman: 2021.12.06.00 - /usr/local/bin/watchman
    Managers:
      CocoaPods: 1.11.2 - /usr/local/bin/pod
    SDKs:
      iOS SDK:
        Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
    IDEs:
      Android Studio: 4.1 AI-201.8743.12.41.6953283
      Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
    npmPackages:
      react-dom: 17.0.2 => 17.0.2 
      react-native-web: 0.17.5 => 0.17.5 
    npmGlobalPackages:
      eas-cli: 0.41.1
      expo-cli: 5.0.3
    Expo Workflow: bare

hirbod avatar Jan 01 '22 20:01 hirbod

P.S: I thought this is the right repo to post this issue. If you feel I have to post this at react-navigation, let me know.

hirbod avatar Jan 01 '22 20:01 hirbod

Can you post this simple repo with the changed applied with e.g. patch-package so we can work on it?

WoLewicki avatar Jan 03 '22 14:01 WoLewicki

@WoLewicki I got rid of it with headerTransparent:true + remove of initialMetrics and some refactoring of my navigators, but I still think that this is bug, because it does not work with all combinations.

hirbod avatar Jan 05 '22 20:01 hirbod

Hmm if you think this is a bug on react-native-screens side, please provide a reproduction so we can work on it.

WoLewicki avatar Jan 07 '22 09:01 WoLewicki

@WoLewicki I will provide a reproduction soon. I think it is indeed a bug on rns.

hirbod avatar Jan 08 '22 12:01 hirbod

@WoLewicki

Here is repo with reproduced bug: https://github.com/pt7892/rnscreens-bottom-tab-flicker

also videos:

https://user-images.githubusercontent.com/20343932/151573753-31677bc2-078f-4697-8fe5-ed64f1f3e1aa.mp4

https://user-images.githubusercontent.com/20343932/151573647-f13466e2-cbf4-4080-bb08-7355ca1c4255.mov

If initial tab screen is simple, you may not notice this, thats why i added bunch of Text and Button components

From what i understand, on tab change, if stack is being mounted first time, 2 RNScreen are being layout on screen, but not in same "tick", and thats why you may notice this flash effect

pt7892 avatar Jan 28 '22 15:01 pt7892

@pt7892 is the jumping behavior connected to the flicker issue you posted here?

WoLewicki avatar Jan 31 '22 11:01 WoLewicki

@WoLewicki

Actually, i was referring to this issue GH-1276, but mistakenly added comment on this one.

I see now that reproduction repo is already uploaded in GH-1276, so this comment can be deleted.

Sorry for the mistake

pt7892 avatar Jan 31 '22 14:01 pt7892

I also have the similar issue. But it happens not only in Initial rendering. It happens every time when I go or come back to the screen inside BottomTabNavigator.

My packages:

"@react-navigation/bottom-tabs": "^6.2.0", "@react-navigation/elements": "^1.3.1", "@react-navigation/material-top-tabs": "^6.1.1", "@react-navigation/native": "^6.0.8", "@react-navigation/native-stack": "^6.5.0", "react-native-reanimated": "^2.4.1", "react-native-safe-area-context": "^3.3.2", "react-native-screens": "3.11.0",

vladyslavNiemtsev avatar Feb 18 '22 12:02 vladyslavNiemtsev

@hirbod Do you have a workaround for it?

vladyslavNiemtsev avatar Feb 18 '22 12:02 vladyslavNiemtsev

@vladyslavNiemtsev please provide a reproduction of this issue then so we can work on it, otherwise we cannot do much about it.

WoLewicki avatar Feb 18 '22 12:02 WoLewicki

hey, when I set headerTransparent: true as described here: https://github.com/software-mansion/react-native-screens#solution The problem with jumping is gone on Android.

But I still have a problem with content cut off on Android.

vladyslavNiemtsev avatar Feb 18 '22 12:02 vladyslavNiemtsev

I think this issue was about iOS, so I am not sure what issue you are mentioning. Or am I missing something?

WoLewicki avatar Feb 18 '22 14:02 WoLewicki

He is indeed right. It is also jumping on android. Only headerTransparent was helping for me

hirbod avatar Feb 18 '22 14:02 hirbod

Just a small point here, if you have headerShown: false in your BottomTabNavigator when you enable it - jumping disappears

hukpo avatar Feb 28 '22 21:02 hukpo

@WoLewicki this is still a thing. The issue comes from where you add headerShown or headerTranslucent.

If you use the header provided by BottomTab, there is no jumping. But when you have a nested stack as a tab, you don't want to use the header from the BottomTab, instead you wan't to use the header provided by the nested stack.

This jumping is still super annoying and there is no real way around it. It just looks like the insets where applied too late and thats what cause the drops. There are repos available in the issue tracker, there is even a duplicated issue: https://github.com/software-mansion/react-native-screens/issues/1276

Would be awesome if we could resolve this.

hirbod avatar May 27 '22 09:05 hirbod

I tried to debug and solve this some time ago but I did not manage to find a solution. If you have any time frame to debug it, it would be really helpful.

WoLewicki avatar Jun 01 '22 13:06 WoLewicki

Iā€™m experiencing the same issue. It seems to be related to the headerShown option. It only happens on first render as well.

With headerShown: false: https://user-images.githubusercontent.com/6510935/173461630-7ddb650d-5ee6-41c0-80de-fa1b8a8fea0d.MOV

With headerShown: true: https://user-images.githubusercontent.com/6510935/173461690-78c17f4b-0481-44c2-a100-dc724a1eabe2.MOV

I found a workaround for this. Instead of using SafeAreaView you will need to style a View component and use the useSafeAreaInsets hook to set the appropriate padding:

import { useSafeAreaInsets } from 'react-native-safe-area-context';
import PropTypes from 'prop-types';
import styled from 'styled-components/native';

const StyledView = styled.View`
  background-color: black;
  flex: 1;
  padding-bottom: ${({ insets }) => insets.bottom}px;
  padding-top: ${({ insets }) => insets.top}px;
`;

export const SafeAreaView = ({ children, ...otherProps }) => {
  const insets = useSafeAreaInsets();
  return (
    <StyledView {...otherProps} insets={insets}>
      {children}
    </StyledView>
  );
};

SafeAreaView.propTypes = {
  children: PropTypes.node,
};

SafeAreaView.defaultProps = {
  children: null,
};

l0gicgate avatar Jun 13 '22 23:06 l0gicgate

useSafeAreaInsets works for me

pjc0247 avatar Jun 24 '22 12:06 pjc0247

Fixed this by swapping <SafeAreaView /> with useSafeAreaInsets()

<View style={[styles.container, { paddingTop: Math.max(insets.top, 16) }]} {...otherProps}>

sjransom avatar Jul 01 '22 20:07 sjransom

@sjransom see my comment here

You cannot use SafeAreaView, you have to create a regular View component and use the useSafeAreaInsets() to pad it appropriately.

l0gicgate avatar Jul 28 '22 05:07 l0gicgate

I've tried using the custom View with useSafeAreaInsets() and I've also tried not using any SafeAreaView at all, and I'm still getting the glitching effect :(

aymather avatar Jul 28 '22 15:07 aymather

@aymather please show the smallest reproducible example possible

l0gicgate avatar Jul 28 '22 17:07 l0gicgate

@l0gicgate Ok so I've tried reproducing the problem... and of course... no dice... but I have recreated a very basic environment to demonstrate a working concept if anyone wants to view it / try to reproduce the problem from there. Here is the repository. (I'll also just add that this environment was created with npx react-native init [name])

I did, however, fix the problem in my app by upgrading react-native-screens from 3.12.0 -> 3.3.0.

Now... I thought that the version might have something to do with the problem, so when I first tried to reproduce the problem, the version that came in when i added react-native-screens was 3.15.0 and the issue wasn't there. So I thought, oh ok.. it was probably something that was patched. So I then downgraded from 3.15.0 -> 3.12.0 to try to reproduce the problem. However, even after downgrading, I still was unable to get the glitch to happen...

For anyone who is still facing this issue, I'd say try removing the package from your project completely, and reinstalling it. Try the 3.3.0 version and see if that works too. Maybe a good-ole-fashioned rm -rf node_modules && rm yarn.json && yarn is all that's needed..? šŸ¤·šŸ»ā€ā™‚ļø

aymather avatar Jul 28 '22 19:07 aymather

Any update on this? Can we have something like "headerTopInsetEnabled" from React Navigation V5 back?

Edit: After wrapping my App with <SafeAreaProvider><App/></SafeAreaProvider> from react-native-safe-area-context it does not jump anymore (no more double height header for a sec).

Rebsos avatar Sep 05 '22 22:09 Rebsos

Hey! šŸ‘‹

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

github-actions[bot] avatar Sep 05 '22 22:09 github-actions[bot]

I'm currently experiencing this issue. Tried all of the solutions above and no luck.

brandon-austin-lark avatar Oct 13 '22 02:10 brandon-austin-lark

Any update on the above issue?

Sumit2202 avatar May 18 '23 20:05 Sumit2202

Facing the same issue!

anhquan291 avatar May 27 '23 05:05 anhquan291

Faced the same issue today

https://github.com/software-mansion/react-native-screens/issues/1251#issuecomment-1154533585

This solution worked

elmaxe avatar Feb 16 '24 09:02 elmaxe