React-native: [NavigatorIOS] doesn't update when navigationBarHidden changes

Created on 14 Apr 2015  路  34Comments  路  Source: facebook/react-native

On my main view, I want to hide navigation bar, but show it in the child views. I pass some props to show/hide the navbar to children, and call them accordingly in componentDidMount/ componentWillUnmount.

Showing works, but hiding doesn't work (or sometimes works, sometimes doesn't).

I have also tested whether it works reliably when just setting it on/off in a single view and it doesn't seem to work. Here is a gist: https://gist.github.com/ustun/5670b7480569fbb784a4

Locked

Most helpful comment

@brentvatne just submitted a pr :)

All 34 comments

i have sample problem with u , and when i change the tarbar, the navigationbar title can't change

I'm also having this issue.

Having this issue as well. Tried to follow the chain that lead to this. This method does get called on state change or on navigator.replace and navgiation.resetTo, but it stops there.

Perhaps the UIKit portion isn't setup for accepting the changes? https://github.com/facebook/react-native/blob/master/React/Views/RCTWrapperViewController.m#L69

Perhaps the work around for now is to setup the first page as non-navigatorIOS page, and the child views to start navigatorIOS routes. You'll loose the swipe back to first page though.

Any more insights on this? I just reverted a lot of code since I was using the 'navigatorIOS' from the second page forward. But then I saw the navigationBarHidden prop and thought it would solve my setup. But I was wrong :)

navigationBarHidden works properly when I use navigator.push, but it doesn't work when I use navigator.replace or navigator.resetTo

@liubko I cannot get that to work. Can you show the code you use to change navigationBarHidden when using navigator.push?

Here is how I do it, with no effect (btw navigationBarHidden was set to false when setting up the NavigatorIOS component):

 this.props.navigator.push({
   component: Login,
   title: "Sign In",
   navigationBarHidden: false, // try it here
 })

 this.props.navigator.navigationBarHidden = false // and here

@jeroenbourgois navigationBarHidden is a prop on NavigatorIOS itself. Passing it in push won't work because those are options for the route. I'm not sure about setting it like this.props.navigator.navigationBarHidden = false.

@jeroenbourgois I save isNavBarHidden status in parent component state.

<NavigatorIOS navigationBarHidden={this.state.isNavBarHidden}
              ref="nav"
              initialRoute={{...}}  />

so then if I do smth like this:

this.refs.nav.push({...});
this.setState({
  isNavBarHidden: ...
});

it works correctly. But it doesn't work when I use replace or resetTo

AHA but of course! Should have seen that.... thanks a bunch!

Still not quite clear how to change isNavBarHidden from a child view .... @liubko how does this.setState is going to fix the problem as the state is at the parent level class

@eltoob when you change state in parent component you then pass it to NavigatorIOS

<NavigatorIOS navigationBarHidden={this.state.isNavBarHidden} />

this will cause a re-render with new navigationBarHidden value

@liubko are you passing the context of the parent component to the child component through the props object?

@alexrabarts you can pass a callback which will change state in parent component
If you are using flux you could trigger some action to update store's isNavBarHidden value, and you will need to listen for that store in parent component.

Actually I ended up using my own header component, to have more control on it

@liubko just a bit confused ... how do you change the state of the NavigatorIOS from a child component ... it doesn't inherit the state from the parent component

@eltoob not sure if we understand each other, I made a demo: https://rnplay.org/plays/L9v2wg

@liubko - great way to demo that :smile:

I fixed this here: https://github.com/brentvatne/react-native-navigator-ios-hide-bugfix/commit/e0655d19821072f7d2ace9bea42902ab50e9d861

If this doesn't seem like too much of a hack, I can follow along those lines and have it update other props as well.

cc @ide

@brentvatne your fix would work when I move from A(no navbar)->B(no navbar)->C(with navbar). But when I move back to B from C, B will show navbar and toggle in B won't work.

Is there any way we can listen on navigator route change? This would fix the problem.

Yeah like @shahbhavir said, this is all good for pushing new views, but does not take into account going backwards.

I need view A (nav bar hidden) to push view B (with nav bar). And then be able to tap back and have the nav bar removed again.

Also take into account supporting the interactive pops by dragging edge of the screen.

In iOS world this is as simple as [self.navigationController setNavigationBarHidden:YES animated:animated]; in viewWillAppear of view A, and [self.navigationController setNavigationBarHidden:NO animated:animated]; in viewWillAppear of view B, but React Native doesn't have those concepts.

@brentvatne I think it is not solved! Please have a look for my demo -> https://rnplay.org/apps/o8dTnw

It is indeed not solved. @shahbhavir has the reason why, and I agree; events for navigation route change would be a straight-forward way to solve this issue.

Has anyone had any luck with a solid solution to hiding the nav bar on the home page (no matter how it's navigated to)?

Pull request for this is welcome! Nobody is currently working on NavigatorIOS, so if you use it then you're as good a person as anyone to make it better :smile:

+1

I updated to react native 0.8 and still have this problem, wish it could be fixed.

The RCTNavigatorItem is wrapped in a little utility class called StaticContainer which prevents the updated state from updating the RCTNavigatorItem.

  <StaticContainer shouldUpdate={shouldRecurseToNavigator}>
    <NavigatorTransitionerIOS
      ref={TRANSITIONER_REF}
      style={styles.transitioner}
      vertical={this.props.vertical}
      requestedTopOfStack={this.state.requestedTopOfStack}
      onNavigationComplete={this.handleNavigationComplete}>
      {items}
    </NavigatorTransitionerIOS>
  </StaticContainer>

https://github.com/facebook/react-native/blob/master/Libraries/Components/Navigation/NavigatorIOS.ios.js#L643-L652

@brentvatne

Your demo here https://github.com/brentvatne/react-native-navigator-ios-hide-bugfix/commit/e0655d19821072f7d2ace9bea42902ab50e9d861 works fine as long as you're pushing the view. Popping doesn't trigger an update.

Now I'm not recommending that anyone do thism but setting getting rid of the StaticContainer or setting shouldUpdate={true}, allows the modification of the state to whatever is passing in navigationBarHidden to the NavigationBarIOS to work.

https://github.com/rollokb/react-native/commit/e5374d271ddd90f4f8e32d34c96631d5606b8fb6#diff-2cc53d7b47c5b24c6942b6b1aec85b40


Perhaps we should look at the logic of how shouldUpdateChild in routeToStackItem is calculated https://github.com/facebook/react-native/blob/master/Libraries/Components/Navigation/NavigatorIOS.ios.js#L592

To hide navigationBar in any chosen view you can change one line in source code.
Then you will be able to pass navigationBarHidden: true directly to any route object.

In node_modules/react-native/Libraries/Components/Navigation/NavigatorIOS.ios.js

in

 _routeToStackItem: function(route: Route, i: number) {
    var Component = route.component;
    var shouldUpdateChild = this.state.updatingAllIndicesAtOrBeyond !== null &&
      this.state.updatingAllIndicesAtOrBeyond >= i;

    return (
      <StaticContainer key={'nav' + i} shouldUpdate={shouldUpdateChild}>
        <RCTNavigatorItem
          title={route.title}
          style={[
            styles.stackItem,
            this.props.itemWrapperStyle,
            route.wrapperStyle
          ]}
          backButtonIcon={resolveAssetSource(route.backButtonIcon)}
          backButtonTitle={route.backButtonTitle}
          leftButtonIcon={resolveAssetSource(route.leftButtonIcon)}
          leftButtonTitle={route.leftButtonTitle}
          onNavLeftButtonTap={route.onLeftButtonPress}
          rightButtonIcon={resolveAssetSource(route.rightButtonIcon)}
          rightButtonTitle={route.rightButtonTitle}
          onNavRightButtonTap={route.onRightButtonPress}
          navigationBarHidden={route.navigationBarHidden}
          shadowHidden={this.props.shadowHidden}
          ...

change

navigationBarHidden={this.props.navigationBarHidden}

to

navigationBarHidden={route.navigationBarHidden}

now you can

this.props.navigator.push({ component: YourComponent, navigationBarHidden: true, })

+1 @katrinanova, this worked for me, thank you!

That's neat @katrinanova :) Want to submit a pull request for this?

@brentvatne just submitted a pr :)

For the record, @katrinanova's PR #5101
Thanks!

Anyone else still having issues?

I'm still having trouble to update simple props like the navigator title by calling navigator.replace in 0.20.

To test things out I tried removing the StaticContainer or setting shouldUpdate={true} but this gives me an error (when calling replace):

Attempting to remove invalid RCT subview of RCTNavigator

I'll keep checking NavigatorIOS.ios.js and RCTNavItem.m. Any suggestions/insights here are obviously appreciated!

@pedro I am still having the same issue in 0.20. Passing navigationBarHidden in replace() or resetTo() does not work, but it does work in push(). I am hacking around this by calling:
push({ navigationBarHidden: false, leftButtonIcon: null, leftButtonTitle: ' ', })

This is not quite a replacement because you still get the push transition, but I'm living with that.

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/navigatorios-doesnt-update-when-navigationbarhidden-changes

ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub. GitHub issues have voting too, nevertheless
Product Pains has been very useful in highlighting the top bugs and feature requests:
https://productpains.com/product/react-native?tab=top

Also, if this issue is a bug, please consider sending a pull request with a fix.
We're a small team and rely on the community for bug fixes of issues that don't affect fb apps.

Was this page helpful?
0 / 5 - 0 ratings