Ian.mc
Ian.mc

Reputation: 1176

react-navigation modal with header/back button

Implementing a social network, I have the Feed screen, a Post screen and a Compose screen

I need to be able to navigate back and forth on the Feed and Post pages, so they're in the same stack.

The Compose screen needs to be popped up as a model with a separate navbar.

The current implementation is this:

const MainStack = new StackNavigator({
    Feed: { screen: Feed },
    Post: { screen: Post },
});

I tried two alternatives:

Adding the compose screen to the main navigator => there's no header, even when overriding navigation options:

export const Navigation = StackNavigator(
  {
    MainStack: { screen: MainStack },
    Compose: { screen: Compose, navigationOptions: { headerMode: "screen" } },
  },
  { headerMode: "none", mode: "modal" }
);

Placing Compose screen in a separate stack => we get a header with a back button, but pressing it doesn't go back to the main stack

const ComposeStack = new StackNavigator({
    Compose: { screen: Compose },    
});

export const Navigation = StackNavigator(
  {
    MainStack: { screen: MainStack },
    ComposeStack: { screen: ComposeStack },
  },
  { headerMode: "none", mode: "modal" }
);

Any help would be greatly appreciated!

Upvotes: 5

Views: 15334

Answers (4)

johnmcveigh
johnmcveigh

Reputation: 11

Simply turn the modal screen into a StackNavigator:

const modalStack = StackNavigator({
  Modal: { screen: Modal }
})

export const Navigation = StackNavigator({
  App: { screen: App },
  Modal: { screen: modalStack },
}, {
  mode: 'modal',
  headerMode: 'none'
})

To return back to the app from the modal:

function handleBackButtonPressed() {
  navigation.goBack(null)
}

Upvotes: 1

edcs
edcs

Reputation: 3879

You can do this without having to manually set a header on your modal screen if you setup your stack navigation in the following way:

export const Navigation = StackNavigator({
  MainStack: { 
    screen: MainStack,
    navigationOptions: { header: null },
  },
  Compose: { 
    screen: Compose,
  },
}, {
  mode: "modal",
});

With this setup, MainStack will render without a header and your Compose modal will have one.

Upvotes: 5

Ian.mc
Ian.mc

Reputation: 1176

I ended up manually placing react-navigation's internal Header component as described here.

Definitely not a perfect solution, but it works.

Would still prefer a better way if somebody knows one.

import Header from 'react-navigation/src/views/Header/Header';

class ModalScreen extends React.Component {
  render() {
   return (
     ...
     <Header scene={{index: 0}}
             scenes={[{index: 0, isActive: true}]}
             navigation={{state: {index: 0}}}
             getScreenDetails={() => ({options: {
                title: 'Modal',
                headerRight: (
                  <Button 
                     title="Close" 
                     onPress={() => this.props.navigation.goBack()}
                  />
                )
             }})}
     />
     ...
   );
  }
}

Upvotes: 0

iridescent
iridescent

Reputation: 383

Try this code. What happens is that now a custom header left button has been specified so that you are able to navigate back to e.g. Post from the modal. You can replace Go Back with a back-arrow icon from a library of your choice.

const MainStack = new StackNavigator({
    Feed: { screen: Feed },
    Post: { screen: Post }
}, {
    headerMode: "screen",
    modal: "card"
});

const ComposeStack = new StackNavigator({
    Compose: { 
      screen: Compose, 
      navigationOptions: ({navigation}) => ({ 
        headerLeft: 
          <TouchableOpacity onPress={()=>{navigation.navigate('Post')}}>
            <Text>Go Back</Text>
          </TouchableOpacity> 
      })
    },    
} );

export const Navigation = StackNavigator({
    MainStack: { screen: MainStack },
    ComposeStack: { screen: ComposeStack },
},
{ 
    headerMode: "none", mode: "modal" 
});

Upvotes: 0

Related Questions