React-navigation 3: Open Modal With Createbottomtabnavigator And Createstacknavigator
Solution 1:
I have found a relatively easy solution:
Hide the original navigation bar with display:"none"
constTabNavigator=createBottomTabNavigator(
{
screen1:Screen1,
screen2:Screen2,
screen4:Screen4,
screen5:Screen5,
}, {
tabBarOptions: {
style: { display:"none", }
}
},);constStackNavigator=createStackNavigator(
{
Home:TabNavigator,
screen3:Screen3
}, {
mode:'modal',
}
)exportdefaultcreateAppContainer(StackNavigator);
And create a new navigation bar on each screen
<View style={{ flexDirection: "row", height: 50, justifyContent: "space-evenly", alignItems: "center", width: "100%" }}>
<TouchableOpacityonPress={() => this.props.navigation.navigate("screen1")}><Text>1</Text></TouchableOpacity><TouchableOpacityonPress={() => this.props.navigation.navigate("screen2")}><Text>2</Text></TouchableOpacity><TouchableOpacityonPress={() => this.props.navigation.navigate("screen3")}><Text>3</Text></TouchableOpacity><TouchableOpacityonPress={() => this.props.navigation.navigate("screen4")}><Text>4</Text></TouchableOpacity><TouchableOpacityonPress={() => this.props.navigation.navigate("screen5")}><Text>5</Text></TouchableOpacity>
</View>
Solution 2:
You can wrap everything inside the same StackNavigator, that way you can navigate to other routes easily. Here i'm passing the screen3 as default route, but you can change that to whatever you'd like.
importReact, { Component, } from'react';
import { createBottomTabNavigator, createStackNavigator, createAppContainer, } from'react-navigation';
import { Screen1, Screen2, Screen3, Screen4, Screen5 } from'./screens';
constTabNavigator = createBottomTabNavigator({
screen1: { screen: Screen1, },
screen2: { screen: Screen2, },
screen3: { screen: () =>null, }, //this.props.navigation.navigate('screen3Modal')screen4: { screen: Screen4, },
screen5: { screen: Screen5, },
});
constStackNavigator = createStackNavigator({
Home: { screen: TabNavigator },
screen3Modal: { screen: Screen3, },
},
{
initialRouteName: 'screen3Modal',
});
constStackNavigatorContainer = createAppContainer(StackNavigator);
exportdefaultclassAppextendsComponent {
render() {
return<StackNavigatorContainer />;
}
}
Solution 3:
Well I have spent hours upon hours to solve this problem.
Here's fully working & tested solution:
- Set up your app container by including tabs stack & to be opened modal navigation stack:
constFinalTabsStack=createStackNavigator(
{
tabs:TabNavigator,
screen1:Screen1Navigator,
}, {
mode:'modal',
}
)
Create app container with that tabs stack per this guide
Inside the
TabNavigator
in thecreateBottomTabNavigator
return null component for specific tab (screen3) (to turn off navigation by react-navigator) and handle the tab manually inside thedefaultNavigationOptions
by creating custom component for it.
constTabNavigator = createBottomTabNavigator({
screen1: Screen1Navigator,
screen2: Screen2Navigator,
screen3: () =>null,
screen4: Screen4Navigator,
screen5: Screen5Navigator,
}
defaultNavigationOptions: ({ navigation }) => ({
mode: 'modal',
header: null,
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state;
if (routeName === 'screen3') {
return<Screen3TabisFocused={focused} />;
}
},
}),
- Handle click manually inside a custom tab component
Screen3Tab
with TouchableWithoutFeedback & onPress. Inside Screen3Tab component:
<TouchableWithoutFeedbackonPress={this.onPress}><Yourcustomtabcomponenthere /></TouchableWithoutFeedback>
- Once you catch onPress dispatch redux event
onPress = () => {
this.props.dispatch({ type: 'NAVIGATION_NAVIGATE', payload: {
key: 'screen3',
routeName: 'screen3',
}})
}
- Handle dispatched event using Navigation Service. I'm using
redux-saga
for it
NavigationService.navigate(action.payload);
A bit complicated but works.
Solution 4:
I've found a better solution based on this github issue.
You just have to add in the specific tab configuration, in your case screen3 the event navigationOptions(you already had it), you were pretty close, but, you had to receive the navigation as a parameter, because there isn't any context for this
as you were using it. To correct the first code that you wrote I would change it to this and it would work:
navigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation }) => {
navigation.navigate("screen3Modal");
}
})
Solution 5:
what can be done is to prevent default action of tab press event and navigate to your desired screen with desired animation.
In my case, i wanted to open a modal in iOS in presentation style which came from iOS 13. what I did was prevent the default action like below
<Tab.Screen name="screen1"
component={ EmptyScreen } // empty screen becuase I want nothing to present here so it was a component that returns null which is given bellow
listeners={({ navigation, route }) => ({
tabPress: e => {
e.preventDefault();
navigation.navigate('modalscreen');
},
})} />
constEmptyScreen = () => {
returnnull
}
'modelscreen' used in above code is from a navigation stack which looks like bellow. Tab navigator for Tab.Screen in the above code is one of the screen in otherstacknavigation which is used in the navigation below.
constMainStack = ({ initialRoute }) => {
return (
<Stack.NavigatorinitialRouteName="otherstacknavigation"screenOptions={{headerShown:false,
gestureEnabled:true,
cardOverlayEnabled:true,
...TransitionPresets.ModalPresentationIOS
}}><Stack.Screenname='modalscreen'component={modalscreen}options={{headerShown:false
}} /><Stack.Screenname='otherstacknavigation'component={otherstacknavigation}initialParams={{initialRoute:initialRoute }}/></Stack.Navigator>
);
}
exportdefaultMainStack;
you can import TransitionPresets like bellow;
import { createStackNavigator, TransitionPresets } from'@react-navigation/stack'
So, in my case, i have first main stack navigator which is MainStack above. It has another stack navigator which is otherstacknavigation in above MainStack. That otherstacknavigation has a screen whose component is Tab navigator. and Tab.Screen in above code is from that Tab Navigator. Now, from one of the tab from this tab navigator, i am navigating to 'modelscreen' which is in MainStack. I had to create this MainStack navigator just to achieve this features otherwise my code would start from otherstacknavigation. Because, ModalPresentationIOS can only be applied to stack level not screen level.
I am using react-navigation-5.* and i think it has answered multiple questions that can arise in such situation.
Post a Comment for "React-navigation 3: Open Modal With Createbottomtabnavigator And Createstacknavigator"