react-navigation / rfcs

RFCs for changes to React Navigation
Other
88 stars 16 forks source link

Discuss cases where shallow navigation options are difficult to use #44

Open brentvatne opened 6 years ago

brentvatne commented 6 years ago

Please take into account the justification in https://github.com/react-navigation/rfcs/blob/master/text/0005-shallow-navigation-options.md when discussing this

iRoachie commented 6 years ago

The solution provided only works for navigators that are direct descendants of the TabNavigator. For nested navigators navigation.state does not change.

// Main Tab navigator
export default createBottomTabNavigator(
  {
    Posts: {
      screen: Posts, // Posts.jsx
      navigationOptions: ({ navigation }: any) => {
        let tabBarVisible = true

        if (navigation.state.index > 0) {
          tabBarVisible = false
        }

        return {
          tabBarVisible,
      },
    },
    Lecturers: {
      screen: Lecturers, // Lecturers.jsx
      navigationOptions: ({ navigation }: any) => {
        let tabBarVisible = true

        if (navigation.state.index > 0) {
          tabBarVisible = false
        }

        return {
          tabBarVisible,
        },
    }
}
// Posts.jsx
export default createStackNavigator(
  {
    posts: {
      screen: Posts,
    },
    viewPost: {
      screen: ViewPost,
    },
    searchPosts: {
      screen: SearchPosts,
    },
  },
  {
    headerMode: 'screen',
  }
)

Posts.jsx works as expected since it's one level deep.


// Lecturers.jsx
const PushStack = createStackNavigator(
  {
    lecturers: {
      screen: Lecturers,
    },
    viewLecturer: {
      screen: ViewLecturer,
    },
    viewCourse: {
      screen: ViewCourse,
    },
  },
  {
    headerMode: 'screen',
  }
)

export default createStackNavigator(
  {
    Main: {
      screen: PushStack,
    },
    newReview: {
      screen: NewReview,
    },
    search: {
      screen: Search,
    },
  },
  {
    mode: 'modal',
  }
)

However Lecturers.jsx doesn't work because it has a nested stack.

Example video: https://www.useloom.com/share/8278cf55d92a452d9818df5e132d0ac7

iRoachie commented 6 years ago

An ideal way I can think of accomplishing this is to introduce a tabBarHiddenOn property that would contain all the screens by key, that the tabBar should be hidden on. By default tabBarVisible would be set to true. This would be a far cleaner solution than writing logic based on the index.

In the above example it could look like this:

export default createBottomTabNavigator(
{
    Posts: {
      screen: Posts,
      navigationOptions: {
        tabBarHiddenOn: [ 'viewPost', 'searchPosts' ]
      }
    }
}
ravirajn22 commented 6 years ago

@brentvatne can you look into this issue. My app update is pending due to this issue. Your current update to this navigationOptions seems not at all intuitive ones navigators start getting nested.

leethree commented 6 years ago

I read the documentation for "A stack contains a tab navigator and you want to set the title on the stack header". The suggested solution works for setting header titles. But it quickly breaks down when we need control things more complicated than the title.

Our problem with the approach is that the navigator needs to know about how the header should behave with each screen. We have some button controls in the header that interacts with the content of the screen. It makes more sense to have the button logic in the navigationOptions of each screen than in the navigator.

See https://github.com/react-navigation/react-navigation.github.io/issues/152#issuecomment-391583282 where I explained the use case before.

ravirajn22 commented 6 years ago

@leethree yes even I faced the same issue, it just doesn't feel right to put the navigationOptions for a particular screen in the navigator and also it does not work when having buttons which setParams. But in those cases, they are recommending to go with the first option of putting each Tab screen as a separate Stack and control the header for these Stacks individually. But I don't know if this is the right way to go.

brentvatne commented 6 years ago

can people create some snacks with examples of their problems please? https://snack.expo.io

iRoachie commented 6 years ago

@brentvatne Here's the snack for my scenario above https://snack.expo.io/@roach_iam/react-navigation-tabs-nested-stacks. As you can see the tabBar doesn't hide for the Lecturers stack.

ravirajn22 commented 5 years ago

@leethree and @iRoachie how did you solve this problem? I am still waiting for a fix to this problem. @brentvatne I think u should look into this issue. What used to be a normal solution in v1.0, seems now like a huge code mess and still, I can't make it work in v2.0.

iRoachie commented 5 years ago

@ravirajn22 I didn’t actually solve it per say. I used a workaround in that I moved all my modals into one navigator at the root of my app.

leethree commented 5 years ago

@ravirajn22 No we haven't found a clean solution for this, so we are still using v1.0 🤷‍♂️

2diegoduque commented 5 years ago

The only thing that worked for me

const homeScreenStack = createStackNavigator({
  Home: {
    screen: Home,
    navigationOptions: ({ navigation }) => ({
      title: "Home"
    })
  },
  Comments: {
    screen: Comments,
    navigationOptions: ({ navigation }) => ({
      title: "Comments"
    })
  }
});

homeScreenStack.navigationOptions = ({ navigation }) => {
  let tabBarVisible = true;
  for (let i = 0; i < navigation.state.routes.length; i++) {
    if (navigation.state.routes[i].routeName == "Comments") {
      tabBarVisible = false;
    }
  }

  return {
    tabBarVisible
  };
};