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.
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 }
);
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)
}
)
Related
navigate works fine however when I replace it with push, it stops working.
<Text
onPress={() => {
//works
this.props.navigation.navigate("VideoPlayer", { id });
// doesn't work
this.props.navigation.push("VideoPlayer", { id });
}}
style={styles.text}
>
{title}
</Text>
How can I get push to work so I can remount components?
I am using a Drawer with a new stack for each route so I can use headers:
const config = {
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63",
itemStyle: {
flexDirection: "row-reverse"
}
},
drawerWidth: 300,
drawerPosition: "right"
};
const withHeader = (
screen: Function,
routeName: string,
Header
): StackNavigator =>
createStackNavigator(
{
[routeName]: {
screen,
navigationOptions: ({ routeName, props }) => ({
header: props => <Header {...props} />
})
}
},
{
transparentCard: true
}
);
const routes = {
Home: {
screen: withHeader(HomeScreen, "Home", BasicHeader)
},
Links: {
screen: withHeader(LinksScreen, "Links", DrawerHeader)
},
Settings: {
screen: withHeader(SettingsScreen, "Settings", DrawerHeader)
},
VideoEpisodes: {
screen: withHeader(VideoEpisodesScreen, "Video Episodes", DrawerHeader)
},
VideoPlayer: {
screen: withHeader(VideoPlayerScreen, "Video Player", DrawerHeader)
},
TestYourself: {
screen: withHeader(TestYourselfScreen, "Test Yourself", DrawerHeader)
},
MyResults: {
screen: withHeader(MyResultsScreen, "My Results", DrawerHeader)
},
BookmarkedVideos: {
screen: withHeader(
BookmarkedVideosScreen,
"Bookmarked Videos",
DrawerHeader
)
},
Search: {
screen: withHeader(SearchScreen, "Search", DrawerHeader)
},
About: {
screen: withHeader(AboutScreen, "About", DrawerHeader)
}
};
const AppNavigator = createDrawerNavigator(routes, config);
export default createAppContainer(AppNavigator);
.push() is a StackAction method, you have to use a stackNavigator in order to use it
I want to update the react-navigation library V2 to V3 and change part of my code thinking that there would not be any problems but it turns out that I have problems creating createStackNavigator with a screen of type createDrawerNavigator and that in turn contains createBottomTabNavigator.
my code that works with the previous version was:
export const createRootNavigator = (signedIn = false) => {
const commonNavigationOptions = {
headerStyle: {
shadowColor: 'transparent',
elevation: 0
},
headerTintColor: DEFAULT_THEME.topaz
};
const SignedIn = createStackNavigator(
{
Home: {
screen: Drawer('Home'),
navigationOptions: () => ({
headerStyle: {
height: 0
},
header: getSafeArea(DEFAULT_THEME.backgrouncolorHomeSafeArea)
})
},
Cards: {
screen: Tabs('Cards'),
navigationOptions: () => ({
headerStyle: {
height: 0
}
})
},
);
const SignedOut = createStackNavigator(
{
SignIn: {
screen: LoginContainer,
navigationOptions: () => ({
headerStyle: {
height: 0
},
header: getSafeArea(DEFAULT_THEME.dark)
})
},
SelectableCardsList: { screen: SelectableCardsListComponent },
);
return createSwitchNavigator(
{
SignedIn: { screen: SignedIn },
SignedOut: { screen: SignedOut }
},
{
initialRouteName: signedIn ? 'SignedIn' : 'SignedOut'
}
);
};
const Drawer = (initialRoute) => createDrawerNavigator(
{
Home: { screen: Tabs('Home') },
{
initialRouteName: initialRoute,
contentComponent: CustomDrawerComponent
}
);
const Tabs = (initialRouteName) => createBottomTabNavigator(
{
Home: {
screen: HomeContainer,
navigationOptions: {
tabBarLabel: I18n.t('tabs.me')
}
},
Home2: {
screen: Home2,
navigationOptions: {
tabBarLabel: I18n.t('tabs.credentials')
}
},
{
initialRouteName: initialRouteName,
tabBarComponent: ({ navigation }) => <CustomBottomBarComponent navigation={navigation} navigationState={navigation['state']} />,
tabBarOptions: {
style: {
backgroundColor: 'white'
}
}
}
);
try this solution with react-navigation V3 and send me an error
I try the following:
encapsulate createSwitchNavigator in createAppContainer and separate (SignedOut and SignedOut) createStackNavigator out of createSwitchNavigator, the rest is still the same.
export const createRootNavigator = (signedIn = false) => createAppContainer(createSwitchNavigator(
{
SignedIn: { screen: SignedIn },
SignedOut: { screen: SignedOut }
},
{
initialRouteName: signedIn ? 'SignedIn' : 'SignedOut'
}
));
I get the following error: The component for route 'Home' must be a react component. For Example
import MyScreen from './MyScreen';
...
Home : MyScreen,
}
you can also use a navigator:
The problem is located in this part:
const SignedIn = createStackNavigator(
{
Home: {
screen: Drawer,
Also try to change Drawer for any component (a component with a blank screen) and this works, but I can not insert the Tabs in the Drawer.
Thank you very much for your help.
my code from that entire page is included below and my entire repo is here:
https://github.com/practicia1234/Practicia/commit/d66a23beece1b293c51b4b791f546a2351e6351b
. I am somehow not able to get this drawer navigation to work. For my model, I used the tutorial from here. This is the repo for that tutorial since it has a similar set up as mine, meaning that the first few screens are sign up and login screens and do not have a drawer exposed to the user. I am not sure what i am doing wrong here and would really appreciate if someone could help me a little. Trying to understand drawer navigation for the first time. Thanks!
Here is the error i get:
import React from 'react';
import { Text, Animated, Easing } from 'react-native';
import { StackNavigator, TabNavigator, DrawerNavigator } from 'react-navigation';
// Home scenes
import Home from '../scenes/Home';
import Dashboard from '../scenes/Dashboard';
// Authentication scenes
import Login from '../scenes/authentication/Login';
import SignUpStep from '../scenes/authentication/SignUpStep';
import SelectTeachers from '../scenes/authentication/SelectTeachers';
// import Dashboard from '../components/Dashboard'
// import FeedScreen from '../components/FeedScreen'
import AwardsScreen from '../scenes/award/AwardsScreen';
// import StudentsScreen from '../components/StudentsScreen'
import GameOnScreen from '../scenes/game/GameOnScreen';
// All practice scenes
import AllPractice from '../scenes/practice/AllPractice';
import Practice from '../scenes/practice/Practice';
import PlayingTests from '../scenes/practice/PlayingTests';
import Questions from '../scenes/practice/Questions';
import Individuals from '../scenes/students/individuals';
import FirstScreen from '../scenes/drawer/FirstScreen';
import SecondScreen from '../scenes/drawer/SecondScreen';
import ThirdScreen from '../scenes/drawer/ThirdScreen';
// Group
import Groups from '../scenes/students/groups';
// Upload
import UploadsScreen from '../scenes/upload/UploadsScreen';
import Pending from '../scenes/students/pending';
//import DrawerContainer from '.../components/DrawerContainer'
// const noTransitionConfig = () => ({
// transitionSpec: {
// duration: 0,
// timing: Animated.timing,
// easing: Easing.step0
// }
// });
// Constant for tab menus
const submissionMenu = {
screen: TabNavigator({
All: { screen: AllPractice },
Practice: { screen: Practice },
PlayingTests: { screen: PlayingTests },
Questions: { screen: Questions }
}, {
tabBarPosition: 'top',
flex: 2 / 3,
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
},
}
}
)
};
const studentMenu = {
screen: TabNavigator({
Individuals: { screen: Individuals },
Groups: { screen: Groups },
Pending: { screen: Pending }
}, {
tabBarPosition: 'top',
flex: 2 / 3,
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
},
}
}
)
};
const DrawerStack = DrawerNavigator({
screen1: { screen: FirstScreen },
screen2: { screen: SecondScreen },
screen3: { screen: ThirdScreen },
});
const DrawerNavigation = StackNavigator({
DrawerStack: { screen: DrawerStack }
}, {
headerMode: 'float',
navigationOptions: ({ navigation }) => ({
headerStyle: { backgroundColor: '#4C3E54' },
title: 'Welcome!',
headerTintColor: 'white',
})
});
const LoginStack = StackNavigator({
home: { screen: Home },
signup: { screen: SignUpStep },
login: { screen: Login },
selectTeachers: { screen: SelectTeachers },
dashboard: {
screen: TabNavigator({
Submissions: submissionMenu,
Students: studentMenu,
Awards: { screen: AwardsScreen },
GameOn: { screen: GameOnScreen },
Uploads: { screen: UploadsScreen }
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#33ACDE',
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 50,
}
}
}),
},
},
{
headerMode: 'float',
navigationOptions: {
headerStyle: { backgroundColor: '#E73536' },
title: 'You are not logged in',
headerTintColor: 'white'
}
});
const navigator = StackNavigator({
loginStack: { screen: LoginStack },
drawerStack: { screen: DrawerNavigation }
}, {
// Default config for all screens
headerMode: 'none',
title: 'Main',
initialRouteName: 'loginStack'
});
export default navigator;
When you execute navigation.navigate('DrawerOpen').
That 'navigation' is not drawer's but StackNavigation's.
If you want to access drawer's navigation, you should call it from children screen in Drawer like FirstScreen, SecondScreen or ThirdScreen.
Execute this.props.navigation.navigate('DrawerOpen') from those Screen.
Consider the render of the Main component:
render() {
const { isAuthenticated } = this.props;
return (
<View>
{isAuthenticated ? <Dashboard /> : <Login />}
</View>
);
I want to lock the drawer in the Login component. Now i know that i could achieve this if Login wasn't a child of Main this way (in my Router component):
Login: {
screen: Login,
navigationOptions: () => ({
drawerLockMode: 'locked-closed',
}),
},
But since Login is a child of Main and Main has the drawer, Login will automatically have the drawer too. I've tried "overriding" it by calling this in Login:
static navigationOptions = {
drawerLockMode: 'locked-closed',
};
But no success. Here's my Router:
const Stack = {
Main: { screen: Main },
Login: {
screen: Login,
navigationOptions: () => ({
drawerLockMode: 'locked-closed',
}),
},
Outbox: { screen: Outbox },
Dashboard: { screen: Dashboard },
JobList: { screen: JobList },
CreateJob: { screen: CreateJob },
Reporting: { screen: Reporting },
JobDescription: { screen: JobDescription },
};
const DrawerRoutes = {
DrawerStack: {
name: 'DrawerStack',
screen: StackNavigator(
Stack,
{
initialRouteName: C.MAIN,
headerMode: 'none',
navigationOptions: {
gesturesEnabled: false,
},
}),
},
};
export const DrawerNavigation = StackNavigator({
Drawer: {
name: 'Drawer',
screen: DrawerNavigator(DrawerRoutes, {
contentComponent: DrawerPanel,
}),
},
...Stack,
}, { headerMode: 'none' });
Is there a way to achieve this ?
please I want to create two DrawerNavigator inside 1 stacknavigator I need the first one will be in Menu Drawer, the second will be for Cart items I need some help or just some ideas how to create this with react-navigation thanks
this my actual implementation
const RootNavigator =
StackNavigator({
Drawer: {
screen: DrawerNavigator(
DrawerRoutesLeft,DrawerContentLeft
)
},
...AnonymousStack
},
{ headerMode: 'none' }
);
let drawerStack = {
Home: {screen: nav_tab},
Rayon: {title:"Rayon" ,screen: Rayon},
Product : {screen :Porduct } }
export let DrawerContentLeft = {
drawerWidth: DEVICE_WIDTH - DEVICE_WIDTH / 5,
contentOptions: {
inactiveTintColor: '#333',
activeTintColor: "#ddd0dd",
},
contentComponent: DrawerContent,
drawerPosition: 'left',
}
let drawerOptions = {
navigationOptions:({navigation}) => ({
headerLeft: <MenuButton navigate={navigation.navigate}/>,
headerStyle:styles.header
}) }
export let DrawerRoutesLeft = {
Home: {
screen: StackNavigator(drawerStack, drawerOptions)
},
Product: {
screen: StackNavigator(drawerStack)
} }