Dmitry Spiridonov
Dmitry Spiridonov

Reputation: 43

Modal navigation for certain screens in react-native app

For 3 screens in my app I need to make a modal transition. For the rest of the screens - I need the default right-to-left transition.

How do I achieve this with different stack navigators?

const AuthStack = createStackNavigator(
  {
    LogIn: { screen: LogInScreen },
    Signup: { screen: SingupScreen },
    Welcome: { screen: WelcomeScreen },
    CodeVerification: { screen: CodeVerificationScreen },
    PasswordSelection: { screen: PasswordSelectionScreen },
    RegistrationSuccess: { screen: RegistrationSuccessScreen }
  },
  {
    initialRouteName: 'LogIn'
  }
)

const ModalNavigator = createStackNavigator({
  ContactInfoEdit: { screen: ContactInfoEditScreen },
  DeliveryAddressEdit: { screen: DeliveryAddressEditScreen },
  OrderPlacedScreen: { screen: OrderPlacedScreen },
},
{
  initialRouteName: 'ContactInfoEdit',
})

const ProductsStack = createStackNavigator(
  {
    Products: {
      screen: ProductsScreen
    },
    Product: {
      screen: ProductScreen
    },
    ProductBuy: {
      screen: ProductBuyScreen
    },
    OrderConfirm: {
      screen: OrderConfirmScreen
    },
    PlaceOrder: {
      screen: PlaceOrderScreen
    },
    Modal: ModalNavigator
  },
  {
    initialRouteName: 'Products',
    mode: 'modal',
  }
)

If I set mode: modal it will make all the navigation animations will be modal. If I remove it, all the navigations will be default (right-to-left)

const ProductsTabStack = createBottomTabNavigator(
  {
    Orders: { screen: OrdersScreen },
    Products: { screen: ProductsStack },
    Profile: { screen: ProfileScreen }
  },
  {
    initialRouteName: 'Products',
    backBehavior: 'none',
    tabBarOptions: {
      activeTintColor: '#ffffff',
      inactiveTintColor: primaryColor,
      activeBackgroundColor: primaryColor,
      labelStyle: {
        marginBottom: 17,
        fontSize: 15,
      },
      tabStyle: {
        shadowColor: primaryColor,
        borderWidth: 0.5,
        borderColor: primaryColor,
      },
    },
  },
)

export const AppNavigator = createSwitchNavigator({
  Auth: AuthStack,
  Categories: ProductsTabStack
})

I tried setting mode: modal in the ModalNavigator, but then it took the default parent navigation.

Upvotes: 3

Views: 2216

Answers (2)

Rachid Rhafour
Rachid Rhafour

Reputation: 456

You probably want to try to use StackNavigatorConfig while navigating to that screen this.props.navigation.navigate('ScreenName', params, {mode: 'modal'})

If you want to keep all your transition code in same file as you have right now, you can do the same as what react-navigation is suggesting here

It goes something like that

import { createStackNavigator, StackViewTransitionConfigs } from 'react- navigation';

/* The screens you add to IOS_MODAL_ROUTES will have the modal transition.  */
const IOS_MODAL_ROUTES = ['OptionsScreen'];

let dynamicModalTransition = (transitionProps, prevTransitionProps) => {
   const isModal = IOS_MODAL_ROUTES.some(
   screenName =>
      screenName === transitionProps.scene.route.routeName ||
   (prevTransitionProps && screenName === 
prevTransitionProps.scene.route.routeName)
)
return StackViewTransitionConfigs.defaultTransitionConfig(
    transitionProps,
    prevTransitionProps,
    isModal
);
};

const HomeStack = createStackNavigator(
  { DetailScreen, HomeScreen, OptionsScreen },
  { initialRouteName: 'HomeScreen', transitionConfig: dynamicModalTransition }
);

Upvotes: 2

Dmitry Spiridonov
Dmitry Spiridonov

Reputation: 43

OK, found a workaround for custom transitions in 1 StackNavigator using https://www.npmjs.com/package/react-navigation-transitions:

const handleCustomTransition = ({ scenes }) => {
  const nextScene = scenes[scenes.length - 1]

  if (nextScene.route.routeName === 'ContactInfoEdit')
    return fromBottom()
  else
    return fromRight()
}

const ProductsStack = createStackNavigator(
  {
    Products: {
      screen: ProductsScreen
    },
    Product: {
      screen: ProductScreen
    },
    ProductBuy: {
      screen: ProductBuyScreen
    },
    OrderConfirm: {
      screen: OrderConfirmScreen
    },
    PlaceOrder: {
      screen: PlaceOrderScreen
    },
    ContactInfoEdit: { screen: ContactInfoEditScreen },
    DeliveryAddressEdit: { screen: DeliveryAddressEditScreen },
    OrderPlacedScreen: { screen: OrderPlacedScreen },
  },
  {
    initialRouteName: 'Products',
    transitionConfig: (nav) => handleCustomTransition(nav)
  }
)

Upvotes: 1

Related Questions