Cannot navigate to route from within navigation stack. - react-native

I have one file with my whole navigation stack. In my navigation header I have a menu and I want to open a Drawer. Now In this example I get the error: Cannot read property 'navigation' of undefined
My AppNavigation file:
import React from 'react';
import { Text } from 'react-native';
import { createStackNavigator, createDrawerNavigator } from 'react-navigation';
import Login from '../components/Login';
import Dashboard from '../components/Dashboard';
import NewNotification from '../components/NewNotification';
const GuestStack = createStackNavigator(
{
loginScreen: { screen: Login },
}, {
headerMode: 'float',
headerLayoutPreset: 'center',
navigationOptions: {
headerStyle: { backgroundColor: '#61b1cd' },
title: 'Welcome',
headerTintColor: 'black',
},
},
);
const LoggedinStack = createDrawerNavigator({
dashboard: { screen: Dashboard },
newNotifciation: { screen: NewNotification },
});
const LoggedinNavigation = createStackNavigator(
{
LoggedinStack: { screen: LoggedinStack },
}, {
headerMode: 'float',
navigationOptions: {
headerStyle: { backgroundColor: '#61b1cd' },
title: 'Welkom!',
headerTintColor: 'black',
headerLeft: <Text onPress = { () =>
this.props.navigation.openDrawer('dashboard')
// navigation.openDrawer('dashboard')
}>Menu</Text>,
},
},
);
const VveNavigator = createStackNavigator(
{
guestStack: {
screen: GuestStack,
},
loggedinStack: {
screen: LoggedinNavigation,
},
}, {
headerMode: 'none',
initialRouteName: 'guestStack',
},
);
export default AppNavigator;
The problem seems to be over here:
headerLeft: <Text onPress = { () =>
this.props.navigation.openDrawer('dashboard')
// navigation.openDrawer('dashboard')
}>Menu</Text>,
And then in my App.js I have
export default class App extends React.Component {
render() {
return (
<APPNavigator />
);
}
}
Version of react navigation is 2.18.1
Thanks

headerLeft doesn't receive navigation prop (check the source code). So if you'd like to use a navigation prop on press, you should consider to refactor your stack navigator config:
const LoggedinNavigation = createStackNavigator(
{
LoggedinStack: { screen: LoggedinStack },
}, {
headerMode: 'float',
navigationOptions: ({ navigation }) => ({ // here you get the navigation
headerStyle: { backgroundColor: '#61b1cd' },
title: 'Welkom!',
headerTintColor: 'black',
headerLeft: (
<Text
onPress={() => {
navigation.openDrawer()
}}
>
Menu
</Text>
),
}),
},
);
Check this issue for more options.

Related

How to acess my stacks from routes.js in App.js

How can i use AppContainer in my main file App.js? And navigate between pages of these two stacks AuthenticationNavigator and MainNavigator
I'm trying to acess my stacks from routes.js in the App.js, but i cant. Can someone tell me what's wrong in the code?
routes.js
const AuthenticationNavigator = createStackNavigator({
Login: {
screen: LoginScreen,
navigationOptions: {
title: 'Login',
headerShown: false, //desabilita a barra do topo
},
},
Register: {
screen: RegisterScreen,
navigationOptions: {
title: 'Cadastro',
},
},
}, {
initialRouteName: 'Login',
defaultNavigationOptions: {
headerTitleAlign: 'center',
headerTintColor: '#FFF',
headerStyle: {
backgroundColor: '#121212',
},
}
})
const MainNavigator = createStackNavigator({
Main: {
screen: MainScreen,
navigationOptions: {
title: 'Main',
headerShown: false,
},
},
}, {
initialRouteName: 'Main',
defaultNavigationOptions: {
headerTitleAlign: 'center',
headerTintColor: '#FFF',
headerStyle: {
backgroundColor: '#121212',
},
}
})
const AppNavigator = createSwitchNavigator({
/*
* Rather than being rendered by a screen component, the
* AuthenticationNavigator is a screen component
*/
Auth: AuthenticationNavigator,
Home: MainNavigator,
}, {
initialRouteName: 'Auth'}
);
const AppContainer = createAppContainer(AppNavigator);
export default AppContainer
The way it's imported in App.js
import AppContainer from "./src/routes"
Where and how i try to acess the stacks(App.js):
render() {
if (!this.state.isAuthenticationReady) {
return (
{}
);
} else {
return (
<>
<StatusBar barStyle="light-content" backgroundColor="#121212" />
{this.state.isAuthenticated ? <AppContainer /> : <AppContainer />}
</>
);
}
}
Make sure you are exporting your all routes like
export {InitialStack, MainStack, Loading}
because you want to use it as
import {InitialStack, MainStack, Loading} from "./src/routes"
And you need to add state in your this line
{this.isAuthenticated ? <MainStack /> : <InitialStack />} // change this to
{this.state.isAuthenticated ? <MainStack /> : <InitialStack />}

Remove header specific page

I have the following page setup in App.js
StackNavigator({
MyTab: {
screen: TabNavigator({ }),
navigationOptions: { title: 'Header title' }
}
})
Bottom tab navigator with 4 screens in it: Home, Search, Card and Account. This tab navigator is inside stack navigator since i will be needing stack navigator to open other screens inside these pages.
In my case I don't need header in the Home page inside tab navigator. But according to this code every page inside tab navigator will have header. How can I achieve this?
Complete code flow is this.
App.js
import HomeScreen from './src/pages/HomeScreen';
import SearchScreen from './src/pages/SearchScreen';
import CartScreen from './src/pages/CartScreen';
import AccountScreen from './src/pages/AccountScreen';
const BottomTabNavigator = createBottomTabNavigator(
{
Home: {
screen: HomeScreen,
},
Search: {
screen: SearchScreen,
},
Cart: {
screen: CartScreen,
},
Account: {
screen: AccountScreen,
},
},
{
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, tintColor}) => {
const {routeName} = navigation.state;
return (
<Image
style={styles.iconSize}
source={require('./src/assets/img/icon.png')}
/>
);
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
style: {
backgroundColor: '#fff',
},
showLabel: false,
indicatorStyle: {
backgroundColor: 'red',
},
},
animationEnabled: true,
swipeEnabled: false,
},
);
const HomeStackNavigator = createStackNavigator(
{
HomeStack: {
screen: BottomTabNavigator,
},
},
{
headerBackTitleVisible: false,
},
);
export default createAppContainer(HomeStackNavigator);
HomeScreen.js
import React, {Component} from 'react';
import {View, Text} from 'react-native';
export default class HomeScreen extends Component {
static navigationOptions = {
header: null,
};
render() {
return (
<View>
<Text> HomeScreen </Text>
</View>
);
}
}
Just add static navigationOptions in your code just anywhere in the code except inside any method like render or componentDidMount, it will work
export default class Home extends Component {
static navigationOptions = {
header: null
}
}
UPDATE:
Try to update your parent stack
const HomeStackNavigator = createStackNavigator(
{
HomeStack: {
screen: BottomTabNavigator,
},
},
{
headerBackTitleVisible: false,
headerMode: 'none',
},
);
Old answer
Try below
export default class Home extends React.Component {
static navigationOptions = () => {
const navigationOptions = {
header: null,
headerMode: 'none',
};
return navigationOptions;
};
}

undefined is not a function (evaluating '(0,_reactnavigationstack.creactDrawernavigation)')

I want to create Drawer Navigation That contains Menu and Home Screen. I tried a lot but I am unable to resolve this issue and as per update of react native we have to wrap the navigation in CreateAppContainer, as you can see i wraped it but nothing is resolved.
"MainComponent"
import React, {Component} from 'react';
import { View, Platform } from 'react-native';
import Menu from './MenuComponent';
import Home from './HomeComponent';
import DishDetail from './DishDetailComponent';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator, createDrawerNavigator } from 'react-navigation-stack';
const MenuNavigator = createStackNavigator({
Menu: { screen: Menu },
DishDetail: { screen: DishDetail }
},
{
initialRouteName: 'Menu',
navigationOptions: {
headerStyle: {
backgroundColor: "#512DA8"
},
headerTintColor: '#fff',
headerTitleStyle: {
color: "#fff"
}
}
}
);
const HomeNavigator = createStackNavigator({
Home: { screen: Home }
}, {
navigationOptions: ({ navigation }) => ({
headerStyle: {
backgroundColor: "#512DA8"
},
headerTitleStyle: {
color: "#fff"
},
headerTintColor: "#fff"
})
});
//-----------Main---------//
const MainNavigator = createDrawerNavigator({
Home:
{ screen: HomeNavigator,
navigationOptions: {
title: 'Home',
drawerLabel: 'Home'
}
},
Menu:
{ screen: MenuNavigator,
navigationOptions: {
title: 'Menu',
drawerLabel: 'Menu'
},
}
}, {
drawerBackgroundColor: '#D1C4E9'
});
class Main extends Component() {
render() {
return(
<View>
<MainNavigator />
</View>
);
}
}
export default createAppContainer(Main);
////////////////////App.js/////////////////
import React from 'react';
import Main from './components/MainComponent';
export default class App extends React.Component {
render() {
return (
<Main />
);
}
}
I think the issue is i am not wrapping the appContainer Correctly.
You are importing wrong. use like
import { createDrawerNavigator } from 'react-navigation-drawer';
import { createStackNavigator } from 'react-navigation-stack';
instead of
import { createStackNavigator, createDrawerNavigator } from 'react-navigation-stack';
Try this way
const LoginNavigator = createStackNavigator({
Login: {
screen: Login,
navigationOptions: {
header: null,
}
},
SignUp: {
screen: SignUp,
navigationOptions: {
header: null,
}
}
});
class NavigationDrawerStructure extends Component {
toggleDrawer = () => {
//Props to open/close the drawer
this.props.navigationProps.toggleDrawer();
};
render() {
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={this.toggleDrawer.bind(this)}>
<Image
source={require('../Img/hamburger.png')}
style={{ width: 25, height: 25, marginLeft: 20, tintColor: '#ffffff' }}
/>
</TouchableOpacity>
</View>
);
}
}
const HomeActivity_StackNavigator = createStackNavigator({
Home: {
screen: Main,
navigationOptions: ({ navigation }) => ({
title: 'Dashboard',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#FF9800'
},
headerTintColor: '#fff'
}),
},
}, {headerLayoutPreset: 'center'});
const DrawerNavigators = createDrawerNavigator({
//Drawer Optons and indexing
Main: {
screen: HomeActivity_StackNavigator,
navigationOptions: {
drawerLabel: 'Dashboard',
}
}
});
const NonDrawerNavigators = createStackNavigator({
TaskView: {
screen: TaskView,
navigationOptions: {
title: 'Task',
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff'
}
},
TeamView: {
screen: TeamView,
navigationOptions: {
title: 'Team',
headerStyle: {
backgroundColor: '#FF9800',
},
headerTintColor: '#fff'
}
}
}, {headerLayoutPreset: 'center'});
const AppNavigator = createStackNavigator({
drawerStack: {
screen: DrawerNavigators,
navigationOptions: {
header: null
}
},
nonDrawerStack: {
screen: NonDrawerNavigators,
navigationOptions: {
header: null
}
}
});
export default createAppContainer(createSwitchNavigator({
SplashScreen: SplashScreen,
loginStack: LoginNavigator,
homeStack: AppNavigator
}, {
initialRouteName: 'SplashScreen'
})
);
I had modified your code as under. I hope this will help you.
"MainComponent"
import React, {Component} from 'react';
import { View, Platform } from 'react-native';
import Menu from './MenuComponent';
import Home from './HomeComponent';
import DishDetail from './DishDetailComponent';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator, createDrawerNavigator } from 'react-navigation-stack';
const MenuNavigator = createAppContainer(createDrawerNavigator(
{
Menu: { screen: Menu },
DishDetail: { screen: DishDetail }
},
{
contentComponent: SideMenu,
drawerWidth: normalize(280),
initialRouteName: "Menu"
}
));
const HomeNavigator = createAppContainer(createStackNavigator(
{
Home: { screen: Home }
},
{
// Default config for all screens
headerMode: 'none',
initialRouteName: 'Home',
// transitionConfig: noTransitionConfig,
},
));
class Main extends Component() {
render() {
return(
<View>
<MainNavigator />
</View>
);
}
}
export default createAppContainer(Main);
////////////////////App.js/////////////////
import React from 'react';
import Main from './components/MainComponent';
export default class App extends React.Component {
render() {
return (
<Main />
);
}
}

How to force drawer to be over header with react navigation

I saw other answers regarding this issue but I can't find solution.
I want to show drawer always above app screen and above header. Instead drawer is always bellow header.
What am I doing wrong here:
const AppNavigation = createStackNavigator(
{
Main: { screen: Main, navigationOptions: {
title: "Main"
} },
Home: { screen: Home, navigationOptions: {
title: "Home"
} }
},
{
initialRouteName: "Main"
}
);
const DrawerNavigation = createDrawerNavigator(
{
Home: Home,
Main: Main
},
{
initialRouteName: "Main"
}
);
App = createStackNavigator({
drawer: {
screen: DrawerNavigation,
},
app: {
screen: AppNavigation
}
}, {
initialRouteName: 'drawer',
navigationOptions: ({navigation}) => ({
headerStyle: {backgroundColor: '#a9a9a9'},
title: 'Welcome!',
headerTintColor: 'white',
headerLeft: <Text onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())}>Menu</Text>
})
});
export default () => (
<View style={{ flex: 1 }}>
<App />
</View>
Our app is similar to this. You can make the drawer be over the header with react-navigation if it is the <Root /> component of your app (the one you import into index.js). For example:
export const Root = DrawerNavigator({
Tabs: {
screen: Tabs,
title: 'Tabs'
},
STACK1: {
screen: STACK1,
title: 'STACK1',
},
STACK2: {
screen: STACK2,
title: 'STACK2',
},
});
That will give you something like this:

How to use both custom TabNavigator and StackNavigator in react-navigation

I'm having some issue with react-navigation.
My navigation routes :
StackNavigator: main app navigation
-- WelcomeScreen
-- GuideScreen
-- TabNavigator: this is CustomTabs
+ MyHomeScreen
+ MyNotificationsScreen
+ MySettingsScreen
-- OtherScreen.
I use createNavigator, createNavigationContainer to build my own Navigation. You can view live for custom tab here: https://snack.expo.io/rJnUK4nrZ
import React from 'react';
import {
Button,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {
createNavigator,
createNavigationContainer,
TabRouter,
addNavigationHelpers,
} from 'react-navigation'; // 1.0.0-beta.11
const SampleText = ({ children }) => (
<Text style={styles.sampleText}>{children}</Text>
);
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => {
navigation.goBack(null);
}}
title="Go back"
/>
</ScrollView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen banner="Home Screen" navigation={navigation} />
);
const MyNotificationsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const CustomTabBar = ({ navigation }) => {
const { routes } = navigation.state;
return (
<View style={styles.tabContainer}>
{routes.map(route => (
<TouchableOpacity
onPress={() => navigation.navigate(route.routeName)}
style={styles.tab}
key={route.routeName}
>
<Text>{route.routeName}</Text>
</TouchableOpacity>
))}
</View>
);
};
const CustomTabView = ({ router, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForState(navigation.state);
return (
<View style={styles.container}>
<CustomTabBar navigation={navigation} />
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
</View>
);
};
const CustomTabRouter = TabRouter(
{
Home: {
screen: MyHomeScreen,
path: '',
},
Notifications: {
screen: MyNotificationsScreen,
path: 'notifications',
},
Settings: {
screen: MySettingsScreen,
path: 'settings',
},
},
{
// Change this to start on a different tab
initialRouteName: 'Home',
}
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
);
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 0,
},
tabContainer: {
flexDirection: 'row',
height: 48,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
margin: 4,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 4,
},
sampleText: {
margin: 14,
},
});
export default CustomTabs;
In the App.js
import { connect } from "react-redux";
import { addNavigationHelpers, StackNavigator } from "react-navigation";
import Welcome from "#components/WelcomeScreen";
import Welcome from "#components/GuideScreen";
import Welcome from "#components/OtherScreen";
// import CustomTabs
export const AppNavigator = StackNavigator(
{
Welcome: { screen: WelcomeScreen },
Guide: { screen: GuideScreen },
Home: { screen: CustomTabs }, // I want to use CustomTabs TabNavigation here?
Other: { screen: OtherScreen },
},
{
initialRouteName: "Welcome",
headerMode: "none"
}
);
const Routes= ({ dispatch, nav }) => (
<AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
);
const mapStateToProps = state => ({
nav: state.nav
});
const mapDispatchToProps = dispatch => ({
dispatch
});
export default connect(mapStateToProps, mapDispatchToProps)(AppWithNavigationState);
How to add my custom TabNavigator to main StackNavigator?
What I'm doing wrong? The app integrated with redux, saga. If you have other example about custom stack and tab using react-navigation, please give me to reference.
Update Your Code:
import Tab1Screen from "#components/Tab1Screen"
import Tab2Screen from "#components/Tab2Screen"
export const AppNavigator = StackNavigator(
{
Welcome: { screen: WelcomeScreen },
Guide: { screen: GuideScreen },
Home: {
screen: TabNavigator(
{
Tab1Screen: {screen: Tab1Screen},
Tab2Screen: {screen: Tab2Screen}
},{
tabBarPosition: "bottom"
})
},
Other: { screen: OtherScreen },
},
{
initialRouteName: "Welcome",
headerMode: "none"
}
);
We can access TabNavigation inside of StackNavigtion
import files
import SampleHeadersScreen from "../Containers/SampleHeadersScreen";
import SampleHeaders1Screen from "../Containers/SampleHeaders1Screen";
import SampleHeaders3Screen from "../Containers/SampleHeaders3Screen";
import SampleHeaders8Screen from "../Containers/SampleHeaders8Screen";
import SampleHeaders9Screen from "../Containers/SampleHeaders9Screen";
const TabSegment = TabNavigator(
{
SegmentBarScreen: {
screen: SampleHeaders8Screen,
navigationOptions: {
title: "Album"
}
},
SegmentBarScreen1: {
screen: SampleHeaders9Screen,
navigationOptions: {
title: "Other"
}
}
})
const PrimaryNav = StackNavigator(
{
LaunchScreen: { screen: LaunchScreen },
SampleHeadersScreen: { screen: SampleHeadersScreen },
SampleHeaders1Screen: { screen: SampleHeaders1Screen },
SampleHeaders3Screen: { screen: SampleHeaders3Screen },
//TabNavigaion
SampleSegmentTab: { screen: TabSegment },
})
Give TabSegment in side the stack nativion.
It work well. I hope it will help you.