Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explain Shallow navigation options workaround for common usecase #152

Closed
fkrauthan opened this issue May 8, 2018 · 25 comments
Closed

Explain Shallow navigation options workaround for common usecase #152

fkrauthan opened this issue May 8, 2018 · 25 comments

Comments

@fkrauthan
Copy link

With Version 2 and the RFC 0005 the way navigation options getting looked up has changed.

In my app (and I've seen many apps using a similar structure) I have the following Navigation/Component Tree

SwitchNavigator 
   -> StackNavigator
       -> WelcomeScreen
       -> TabNavigator
           -> Tab1Screen
           -> Tab2Screen
           -> Tab3Screen

For my WelcomeScreen it correctly uses for the Header the title attribute defined in navigationOptions. But for Tab1Screen, Tab2Screen and Tab3Screen I don't seem to have any way to manipulate the Header title or for that matter any Header attribute?

I would like my Top title to change with different Tabs and in addition for some Tabs to display a Button on the right side of the Header. What would be the new recommended way to approach this? Or is this currently not possible?

@JimmyMultani
Copy link

I'm following a similar stack, and my screens' navigationOptions are not updating anything in the header anymore. Without a proper example, I've been struggling to find a solution to this as well.

Any assistance on this would be greatly appreciated.

@brentvatne
Copy link
Member

what would you say is missing from https://reactnavigation.org/docs/en/navigation-options-resolution.html?

@fkrauthan
Copy link
Author

@brentvatne Given the documentation you are linking I can not figure out how to solve my explained usecase of individual header title and buttons per Screen that is in a TabNavigator which in Return is in a StackNavigator.

@brentvatne
Copy link
Member

so you want some screen deep in your navigation hierarchy to update a header at the root of the hierarchy?

@fkrauthan
Copy link
Author

Correct. Its a very common scenario seen in many modern apps. And even tho the screen is deep in the hierarchy its still the first screen that is referenced after a Navigator (so no nesting within my screen components itself)

@brentvatne
Copy link
Member

brentvatne commented May 8, 2018

i think it may seem like this is what happening, but actually these screens are likely to have their own headers.

some options for you:

  • put stack navigators inside each tab, use headers there, set header: null in navigationOptions on your tab navigator myTabNavigator.navigationOptions = { header: null }
  • set title on tab navigator depending on route:
myTabNavigator.navigationOptions = ({ navigation }) => {
  let headerTitle = '';
  let { routeName } = navigation.state.routes[navigation.state.index];
  if (routeName === 'Tab1') {
     headerTitle = 'My First Tab';
  } // etc..

  return {
    headerTitle,
  };
};

@brentvatne
Copy link
Member

also see: react-navigation/rfcs#44 if you have feedback about how this works and cases where you can't do something that you need to do

@fkrauthan
Copy link
Author

fkrauthan commented May 8, 2018

I find that solution quiet complex and goes against component best practice in React. Now my TabNavigator all the sudden needs logic of What Tabs it actual displays and what there header needs are. To me that feels wrong.

And why should I add a Stack Navigator inside my Tab if I don't plan to use a Stack in there? It might lead to more issues as I need todo navigation in the top stack where the tab itself is in.

@brentvatne
Copy link
Member

I find that solution quiet complex and goes against component best practice in React.

which one? what's complex about it? your tab navigator already knows what tabs it displays, it's in the definition directly above where I would put that navigationOptions code

And why should I add a Stack Navigator inside my Tab if I don't plan to use a Stack in there? It might lead to more issues as I need todo navigation in the top stack where the tab itself is in.

you want a header there, stack gives you ui for header

@fkrauthan
Copy link
Author

But wouldn't I need to set the Top StackNavigator to not use a Header aswell? Or does it only pick the lowest StackNavigator to display the Header?

@brentvatne
Copy link
Member

set header: null on navigationOptions for the tab navigator

@brentvatne
Copy link
Member

also, this having a stack in each tab is probably what you would want in the vast majority of cases. usually you want the tab bar to remain visible when you navigate to subscreens within a tab

@fkrauthan
Copy link
Author

Well I can name you without even thinking already one big exception the google play appstore. Another one is Instagram (they use Tabs when on a profile to switch between your uploads and your tagged photos) and when you click on a photo it goes away. And I am sure there are many more like that.

@brentvatne
Copy link
Member

brentvatne commented May 9, 2018

instagram doesn't do that? instagram works how i described it :P (I'm talking about iOS here, Android is almost entirely irrelevant to this discussion because headers are rendered separately for each screen)

@doomsower
Copy link

I faced same issue some time ago, while v2 was still in beta, and my experiments with workarounds were never commited, so no concrete examples here. Maybe someone can provide example or suggest workaround.

I had stack -> tabs -> stack hierarchy and ended up with just two levels stack -> tabs. The suggested by @brentvatne workaround with header: null didn't work because of two things:

  1. Weird headers animation when switching between stack navigators of different levels
  2. Back button issues. When deeper stack has only 1 screen, it won't show back button. However I still need it, to go back to previous tab or back in root stack or whatever upper nav hierarchy screens might need it for.

So now I have to implement this "get current route and switch" workaround for header top-right button for different tabs. I don't like this because basically I have to maintain two navigation hierarchies. If I change something in main navigation hierarchy and forget to update this top-right button switch logic, then things break. Another alternative I'm considering is having portal in header and rendering things into portal right from screens.

Maybe some official helper for this switch behavior would make things a bit simpler.

@leethree
Copy link

We have a similar navigation stack:

StackNavigator
       -> ProductScreen
       -> ShoppingCartScreen
       -> TabNavigator
           -> MainTabScreen
           -> ShoppingCartScreen
           -> OtherTabScreen

Notice that the same ShoppingCartScreen is added to both Stack and Tab navigator. We have a button on the header of ShoppingCartScreen to toggle its editing state via navigation.setParams().

This works fine in v1 because the header "propagates" from Tab to Stack. ShoppingCartScreen works great in both Tab or Stack without knowing which navigator it's in.

However in v2 the only workaround that works is to add another layer of StackNavigator to each screen in the TabNavigator. I haven't tried it but I'm not optimistic based on other comments in this thread.

@leethree
Copy link

Android is almost entirely irrelevant to this discussion because headers are rendered separately for each screen

@brentvatne Could you elaborate on this one? I'm seeing the exact same problem on Android. I don't see why this discussion is specific to iOS.

IMO Tab nested in Stack is a valid use case. It's very common among Android apps and shopping apps. A general-purpose navigation library should not be opinionated about this.

@brentvatne
Copy link
Member

see: 034649d

@brentvatne
Copy link
Member

@brentvatne
Copy link
Member

if anybody encounters issues that aren't handled by the use cases documented there, let me know and we can add more and use this in the future if we decide to ease up on shallow navigation options and perhaps at some utilities to let you dive deeper

@fkrauthan
Copy link
Author

@brentvatne So the basic suggestion is to recreate the header logic etc in my navigation stack instead of the Screen where it should belong too correct? I guess until we have at least a option for nested navigation props similar to V1 I can not upgrade as it would add way more code at places where I think it shouldn't be.

@brentvatne
Copy link
Member

@fkrauthan - there are two options presented for what you described above. I'd suggest putting stacks inside tab navigator, which is one of those options

@brentvatne
Copy link
Member

@fkrauthan - but if you really don't like that solution, @bakerface has an alternative discussed in react-navigation/react-navigation#4309

@bakerface
Copy link

@fkrauthan I created react-navigation-options-from to help address my issues with nested navigators. Let me know if that helps with the issues you are facing.

@brentvatne
Copy link
Member

brentvatne commented Dec 5, 2018

@ThaJay - please don't use this library anymore

edit: for clarification, people are welcome to criticize design decisions but please provide actionable feedback and try to consider why the decision was made in the first place (in this case, there is a rfc which is mentioned in the first sentence of this issue: https://github.com/react-navigation/rfcs/blob/master/text/0005-shallow-navigation-options.md). joining in to an issue to simply call it a stupid decision will result in a temporary ban from being able to interact with the organization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants