In my app I have three screens: ScreenA
, ScreenB
and ScreenC
. They all should have a header and they should all have a back button with the name of the previous screen. I wanted ScreenA
to be able to open ScreenB
using the modal animation:
const ModalStack = createStackNavigator(
{
ScreenA,
ScreenB
},
{
initialRouteName: "ScreenA",
mode: "modal"
}
);
And ScreenA
should also be able to open ScreenC
using the default sliding animation from right to left. The problem was, that the StackNavigator was already configured with the modal mode. Is there a way to dynamically set the mode? So that from ScreenA
to ScreenB
modal is used and from ScreenA
to ScreenC
card?
Furthermore how to handle the header in this case? (For the reason why I ask this question, please read further.)
Here is what I tried after reading the documentation. It describes a similar scenario.
Here is how this tutorial translated for me:
const SlidingStack = createStackNavigator(
{
ScreenA,
ScreenC
}
);
const ModalStack = createStackNavigator(
{
SlidingStack,
ScreenB
},
{
mode: "modal"
}
);
The problem with this solution is, that the header now renders double when I'm on ScreenA
. Furthermore when I open the modal ScreenB
the back button is blank.
Edit
In my attempt to solve this problem following the documentation, I found a solution for the double header rendering:
const SlidingStack = createStackNavigator(
{
ScreenA,
ScreenC
}
);
const ModalStack = createStackNavigator(
{
SlidingStack,
ScreenB
},
{
mode: "modal",
navigationOptions: ({ navigation }) => {
const options = {}
if (navigation.state.routeName === "SlidingStack") options["header"] = null;
return options;
}
}
);
The problem with this solution is, that the back buttons still do not have any text.
Edit:
Following what I've learned from Pritish, here is the code I ended up with:
const IOS_MODAL_ROUTES = ["OptionsScreen"];
let dynamicModalTransition = (
transitionProps: NavigationTransitionProps,
prevTransitionProps: NavigationTransitionProps
): TransitionConfig => {
if (
IOS_MODAL_ROUTES.some(
screenName =>
screenName === transitionProps.scene.route.routeName ||
(prevTransitionProps && screenName === prevTransitionProps.scene.route.routeName)
)
) {
return StackViewTransitionConfigs.defaultTransitionConfig(
transitionProps,
prevTransitionProps,
true
);
}
return StackViewTransitionConfigs.defaultTransitionConfig(
transitionProps,
prevTransitionProps,
false
);
};
It uses React Navigation V2's owns transitions.
Going back to the docs
headerBackTitle
:: Defaults to the previous scene'sheaderTitle
In your implementation, you're trying to move from
ScreenA
toScreenB
, where the header of theScreenA
is null, therefore the back button doesn't contain a title.There will always be a case (as per your design) that you transition from a non header screen to a header screen, hence this solution won't work.
A workaround for that would be to create a Transitioner with a
default
(a screen transition) andmodal
Transition (a modal transition), and set it in thetransitionConfig
options of the StackNavigatorConfig asand use transition params while navigating if you want to have a modal as