React-native-navigation: Top bar title component blinks when changing pages

Created on 27 Aug 2018  路  31Comments  路  Source: wix/react-native-navigation

Issue Description

When switching pages the topBar's title blinks if you are using a component instead of text. This happens even if it is a super simple component that only returns <Text>test title</Text>.
Previously when using a custom component for the whole topBar it did not blink and appeared immediately between page renders

Steps to Reproduce / Code Snippets / Screenshots

Navigation.setStackRoot(this.props.componentId, {
    component: {
        name: 'teams',
        passProps: { teams: true },
        options: {
            topBar : {
                title: {
                    component: {
                        name: 'CustomTopBar',
                        alignment: 'fill'
                    },
                }
            },
        },
    }
});

export default class TopBarHeader extends BaseComponent {
    constructor() {
        super(...arguments);
    }
    static displayName = 'TopBar:Header';

    render() {
        return <Text>test</Text>
    }
}

Environment

  • React Native Navigation version: 2.0.2502
  • React Native version: 0.56
  • Platform(s) (iOS, Android, or both?): both
Android acceptebug 馃彋 stale

Most helpful comment

@guyca how's this looking? Is it a complex change? I'm also getting flickering with react components inside top bar buttons.

All 31 comments

same issue. any resolution?

Same issue here. Kind of got around the issue by setting dimensions to the component, so instead of flickering it fades when changes tabs. Still not great tho.

Mine is flickering showing three dots for a sec and jumping left/right sides.
Take a look (screen captured from Genymotion but same issue on real device)
screen-recording- 9-5-2018-3-21-17-pm
The topBar is configured as following:

topBar: { drawBehind: false, animate: false, background: { color: '#d94515' }, title: { fontSize: 16, color: '#FFFFFF', fontFamily: 'Helvetica', alignment: 'center' } }

@FeniXenAaaa Can you please update the latest version any see if you still see the three dots issue?

I tested with the following component and didn't see three dots

const React = require('react');
const {
  Text
} = require('react-native');

class SimpleTopBarHeader extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
        <Text>test123</Text>
    );
  }
}

Regarding the "blink" issue - I think it's because it takes time for a react component to render... need to think how this can be addressed atm.

@guyca updated to 2.0.2556. Still got both issues but kinda less visible. But now I'm starting to get weird error. Take a look:
screen-recording- 9-19-2018-5-11-32-pm

image

@FeniXenAaaa Doesn't seem like this red screen is related to this issue.
I still can't reproduce the ellipsis issue - maybe it's related to the component you're displaying. Can you share your component's code with us?

@guyca I'm not using any custom component, I'm just using bare title but this issue still exists for me

@guyca I have the same issue on Android with the lastest version (2.0.2569)

topbar_flickers_bug_android

My topbar component looks like this.

import React from 'react';

import {
  CachedImage,
  ImageCacheProvider,
} from 'react-native-cached-image';

import {
  ImageBackground,
  StyleSheet,
  View,
  Dimensions,
} from 'react-native';

import images from '../../images';

const screenWidth = Dimensions.get('window').width;

export default () => {
  console.disableYellowBox = true;
  const Image = (
    <ImageCacheProvider>
      <CachedImage
        resizeMode="contain"
        source={images.logo_small}
        style={styles.logo}
        ttl={60 * 60 * 24 * 365}
      />
    </ImageCacheProvider>
  );

  return (
    <View style={styles.topBarContainer}>
      <ImageBackground
        source={images.top_bar_background}
        style={styles.imageBackgroundContainer}
        resizeMode="cover"
      >
        {Image}
      </ImageBackground>
    </View>
  );
};

const styles = StyleSheet.create({
  topBarContainer: {
    backgroundColor: '#d64e55',
    width: '110%',
    height: 60,
    left: -20,
    top: 0,
    shadowColor: 'rgba(0,0,0, .5)',
    shadowOffset: { height: 1, width: 2 },
    shadowOpacity: 1,
    shadowRadius: 2,
  },
  imageBackgroundContainer: {
    backgroundColor: '#d64e55',
    width: screenWidth,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    height: 60,
    position: 'absolute',
    zIndex: 0,
    marginLeft: 20,
  },
  logo: {
    marginTop: 5,
    width: 45,
    height: 45,
  },
});

Any ideas whats wrong?

@simonhintersonnleitner
This is caused by a design short sight - options are applied when a view is attached to hierarchy and visible. In some cases this is too late, for example when a react view is displayed in the TopBar. React views take time to render, typically less then 100 ms.

I'll address this issue asap

@guyca how's this looking? Is it a complex change? I'm also getting flickering with react components inside top bar buttons.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

The issue has been closed for inactivity.

@guyca This is moved to Done but the problem is still present.
If you use a component it flickers because as you mention it takes time to render.

I don't see any commit on this or PR merged, why is this closed so?

Bot has closed this for inactivity. It is still a glaring issue, and an important one at that.

Still seeing the flicker on my top bar component, is there any more movement on this?

this issue still exist in the latest version

@guyca @yogevbd @ItsNoHax Hello guys! This indeed shouldn't be closed, as many of us are still in trouble with the issue. Can you guys give us some advice on how to start to fix this or any ETA? Thank you

@simonhintersonnleitner
This is caused by a design short sight - options are applied when a view is attached to hierarchy and visible. In some cases this is too late, for example when a react view is displayed in the TopBar. React views take time to render, typically less then 100 ms.

I'll address this issue asap

Based on this I started looking in the source code. Basically the problem is related to the fact that on screen push, there is a call to clearOptions which is removing our custom component background from the topBar and then we are re-adding the view on the pushed screen.
TopBar is shared among screens (btw I don't understand why, if you can give us some more info on why you make this choice would be great!).
My current idea is to avoid to remove the custom component if starting screen and landing screen share the same custom component Id.

TopBar.java

public void clear() {
  if (component != null && !((TopBarBackgroundView) this.component).getComponentName().equals(((TopBarBackgroundView) root.getChildAt(0)).getComponentName())) {
      root.removeView(component);
      component = null;
  }

  titleBar.clear();
}
public void setBackgroundComponent(View component) {
  this.component = component;
  if (root.getChildAt(0) instanceof LinearLayout) {
       root.addView(component, 0);
   }
}

This implementation is terrible, but I've got a working result. With those lines of code, if you push a screen with the same custom background as the starting screen, you'll see no flicker.
Do you guys have any better idea on how to proper implement this? Should we pass a prop from the options to enable this check?
Any help is really appreciated!

Came up with this https://github.com/wix/react-native-navigation/pull/5110 after texting a bit with @guyca, this should fix the flicker of custom background of the topbar

I'm encountering this same 'blinking' issue on iOS with the latest version (2.20.2)

@julaak How's your setRoot?

@FRizzonelli setRoot looks roughly like this

Navigation.setRoot({
    root: {
      sideMenu: {
        right: {
          component: {
            name: 'SideMenu'
          },
        },
        center: {
          bottomTabs: {
            children: [
              {
                stack: {
                  children: [
                    {
                      component: {
                        name: 'SomeScreen',
                        options: {
                          bottomTab: {
                            text: 'Home',
                            icon: require('./images/bottomTabs/icon.png')
                          }
                        }
                      }
                    }
                  ]
                }
              },
              ....more children...
            ]
          }
        }
      }
    }
  });

Inside the screens we're using the Navigation.push() API to move to another screen.

Navigation.push(this.props.componentId, {
      component: {
        name: "OtherScreen"
      }
});

Inside the screens we use Navigation.mergeOptions() API to change the topBar title component, which is when the blinking happens.

    Navigation.mergeOptions(this.props.componentId, {
      topBar: {
        visible: true,
        title: {
          component: {
            name: 'ComponentName',
            alignment: 'center',
            passProps: {
              title: 'Top Bar Component Title',
              onPress: () => this.onTopBarPressed(),
              otherData: otherData
            }
          }
        }
      }
    });

Every time we use the Navigation.mergeOptions() API, the top bar contents (title component) blinks,
even though only the passProps change. I guess the optimal behaviour would be to re-use the existing component in this case. However I'm not familiar how the underlying code works and if that is feasible.

This workaround works like magic. Give it a try guys:
https://medium.com/@linasmnew/react-native-navigation-wix-fix-top-left-corner-flickering-bcf5f9aa57cd

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

The issue has been closed for inactivity.

I am facing this issue. My header section is flickering any solution for this?

No deal for me, still blinking on android using 6.5.0

@drixbarsali Have you tried assigning the same id to the background component?

topBar: {
  background: {
    component: {
      name: 'SomeComp',
      id: 'bgCompId'
    }
  }
}

If it doesn't work, please test it on both platforms are report back. Thanks!

I have tested real quick and seems it works on both platforms, is a little jumpy, but i think the problem is with my style... gonna do more teste, but thanks :)

@guyca did not work... let me explain it better, what is happening is this.. I have component setted as title, everytime on android that i push a screen it blinks... did not happens on IOS

Screenrecorder-2020-05-26-12-03-18-401

topBar: { visible: mergedOptions.topBarVisible, title: { component: { id:"customHeaderNew", name: 'CustomHeader', passProps: { route: { params: mergedOptions.routeProps }, alignment: 'center', waitForRender: false, }, }, }, background: { color: mergedOptions.topBarBackground, }, backButton: { visible: false, }, },

This issue still exists on RN 0.63.4 & react-native-navigation 7.8.1, while setting tabsAttachMode to onSwitchToTab.
With the default value (together), the topbar blinks only when setRoute is called.

Since there is not actual solution to use tabs navigation with onSwitchToTab mode and get the top bar blinks, the last (extrem) solution for me was to switch on react-navigation, from there you can use tabs navigation with lazy loading (corresponding to onSwitchToTab), and without top bar blinks.

Was this page helpful?
0 / 5 - 0 ratings