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

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

  • iOS
  • Android
  • Web
  • Windows
  • tvOS

Workflow

  • Managed workflow
  • 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

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 6
  • Comments: 30 (11 by maintainers)

Commits related to this issue

Most upvoted comments

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

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,
};

@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

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.

useSafeAreaInsets works for me

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