I upgraded to react-navigation V5, and am so confused how to get the Drawer to work. I had a custom drawer before, but now I'm just trying to get a sample drawer working.
I am trying to open the drawer with this.props.navigation.dispatch(DrawerActions.toggleDrawer())
The action 'TOGGLE_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
Here are the relevant files:
MessagesStackRouter.js
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
function DrawerNavigation() {
return (
<Drawer.Navigator
drawerType={"slide"}
>
<Drawer.Screen name="Dash" component={DashboardContainer} />
</Drawer.Navigator>
);
}
function MessagesStackRouter() {
return (
<NavigationContainer>
<Stack.Navigator
initalRoute="Login"
screenOptions={{ gestureEnabled: true, headerShown: false }}
>
<Stack.Screen name="Login" component={LoginView} />
<Stack.Screen name="DrawerNavigation" component={DrawerNavigation} />
<Stack.Screen name="Dashboard" component={DashboardContainer} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default MessagesStackRouter;
App.js
return (
<View style={{flex:1, backgroundColor: 'white'}}>
<StatusBar hidden={true} />
<Provider store={createStore(reducers)}>
<MessagesScreenRouter/>
</Provider>
</View>
);
relevant parts of TopNavBar.js
import { DrawerActions } from '#react-navigation/native';
class TopNavBar extends Component {
constructor(props) {
super(props);
this.onBurgerBarPress = this.onBurgerBarPress.bind(this)
}
onBurgerBarPress() {
this.props.navigation.dispatch(DrawerActions.toggleDrawer())
}
render() {
return (
<View style={styles.navBar}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: 10 }}>
<TouchableOpacity onPress={()=> this.onBurgerBarPress()}>
<Icon
name={"Menu"}
strokeWidth="1.5"
stroke={'#03A9F4' }
fill={'#03A9F4'}
/>
</TouchableOpacity>
</View>
</View>
)
}
};
const mapStateToProps = (state) => {
return {
onboarding: state.onboarding,
currentUser: state.currentUser
}
}
export default connect(mapStateToProps, actions)(TopNavBar);
You get an error because the screen where you have the drawer navigator is not rendered. You should nest the stack navigator inside the drawer navigator instead of drawer inside stack which will work better for your case.
Related
I'm new to React Native and trying to learn. but I couldn't do what I wanted to do.
I have Tab Navigations and I want to Open Stack when I click the button. But I can't figure out how to do it, thanks in advance for your help.
Snack
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Details} />
</Stack.Navigator>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
Your tabs can take a StackNavigator as the component and by default it will go to the first screen in that stack when you press the tab.
edit to your code
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
The navigation.navigate(...) part becomes a little more complicated but not too bad. See the example here. This one is basically opposite of your setup where the tabs are nested within a stack navigator.
Anyone know why I cant call toggleDrawer on navigation from my Header here? I assume that the navigation prop should be provided by default to Drawer.Navigator, but it seems to be undefined.
App.js
import { NavigationContainer, DefaultTheme, DrawerActions } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeScreen from './screens/HomeScreen';
import Header from './components/Header';
import Background from './components/Background';
const theme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: 'transparent',
},
};
const Drawer = createDrawerNavigator()
export default function App() {
return (
<NavigationContainer theme={theme} >
<Background />
<Drawer.Navigator initialRouteName="Home" screenOptions={{ header: () => <Header options={{headerStyle: {height: 200}}} /> }}>
<Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Header.js
const Header = ( {navigation, route, options, back}) => {
const [fontsLoaded] = useFonts({Kanit_400Regular, Kanit_500Medium, Kanit_700Bold})
if (!fontsLoaded) return <LoadingSpinner />
return (
<View style={options.headerStyle}>
<View style={styles.headerContainer}>
<TouchableOpacity style={styles.hamburgerContainer} onPress={() => navigation.toggleDrawer()} >
<View>
<View style={styles.hamburgerLine}></View>
<View style={styles.hamburgerLine}></View>
<View style={styles.hamburgerLine}></View>
</View>
</TouchableOpacity>
</View>
)
}
When I press the hamburger menu:
The navigation object will be passed to a custom header by the library. However, you are not passing the props to your custom component.
You can pass the props from the library to your header component as follows.
<Drawer.Navigator initialRouteName="Home" screenOptions={{ header: (props) => <Header {...props} options={{headerStyle: {height: 200}}} /> }}>
<Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>
I was following the React navigation to create the pages, however, I only get the blank page when I build the application.
https://reactnavigation.org/docs/hello-react-navigation
React navigation version
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"#react-navigation/stack": "^6.0.11",
Here is my full code on App.js
On this page, I created 3 function: HomeSc, HomeScCheck, DetailSc.
Only the HomeScCheck can show on the screen.
import * as React from 'react';
import { View, Text , SafeAreaView} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScCheck() {
return (
<View><Text style={{color:"red"}}>Home Screen Check</Text></View>
);
}
function HomeSc() {
return (
<View><Text>Home Screen</Text></View>
);
}
function DetailSc() {
return (
<View style={{ flex: 1}}>
<Text style={{color: '#333', fontSize:30}}>Detail Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<SafeAreaView>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeSc} />
<Stack.Screen name="Detail" component={DetailSc} options={{ title: 'Overview' }} />
</Stack.Navigator>
</NavigationContainer>
<HomeScCheck/>
</SafeAreaView>
);
}
export default App;
As you were saying that you want to see the HomeScCheck screen as the first screen, you should see when the app is run.
So, to do that your code should look as the following code.
import { View, Text, SafeAreaView } from 'react-native';
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScCheck() {
return (
<View>
<Text style={{ color: 'red' }}>Home Screen Check</Text>
</View>
);
}
function HomeSc() {
return (
<View>
<Text>Home Screen</Text>
</View>
);
}
function DetailSc() {
return (
<View style={{ flex: 1 }}>
<Text style={{ color: '#333', fontSize: 30 }}>Detail Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home Check" component={HomeScCheck} />
<Stack.Screen name="Home" component={HomeSc} />
<Stack.Screen
name="Detail"
component={DetailSc}
options={{ title: 'Overview' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
So, What I have done is that I have removed the <safeareaview> and <HomeScCheck> and I have created another <Stack.Screen> above the home <Stack.Screen>. Though this tells that the first <Stack.Screen> will be the first screen of the stack navigator.
Kindly remove safeAreaView and statusbar from the App.js file
only put Navigation inside the return
I'm trying to introduce DrawerNavigation under StackNavigation. My StackNavigation is working fine. But when I'm dragging the screen DrawerNavigation is not working. Nothing happens...No errors also.
I am using TouchableOpacity for the list items. Though I don't think so, is there any chance it is occurring due to the first touch on list-item??? If not, then can anyone point me out what the issue is? I really appreciate any help you can provide.
I have given my Navigator.Js code here and a video Url to understand better what is happening for my case.
Video URL - https://drive.google.com/file/d/1MhD3gB8Pp4tqbXr1HktOPa-2xOqW0xoA/view?usp=sharing
Instead of wrapping DrawerNavigator inside StackNavigator, wrap your StackNavigator inside DrawerNavigator.
Working Example: Expo Snack
Output:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const StackNav = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={() => <Text>Login</Text>} />
<Stack.Screen name="Register" component={() => <Text>Register</Text>} />
</Stack.Navigator>
);
};
export default function App() {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Stack" component={StackNav} />
<Drawer.Screen
name="HomeNews"
component={() => (
<View style={styles.container}>
<Text>HomeNews</Text>
</View>
)}
/>
<Drawer.Screen
name="StateNews"
component={() => (
<View style={styles.container}>
<Text>StateNews</Text>
</View>
)}
/>
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
I am using Drawer,Stack and Tab navigator using React Navigation 5, I have followed documentation but Tab Navigator not showing.
Here's my code:
In my app.js I have called my main StackNavigator:
const Stack = createStackNavigator();
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none" initialRouteName="HomePage">
<Stack.Screen name="Home" component={HomePage} />
<Stack.Screen name="Login" component={LoginSignUp} />
<Stack.Screen name="DrawerScreenss" component={DrawerScreens} />
<Stack.Screen name="Tab" component={TabComp} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
This is my Drawer Navigation Code:
import * as React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import DrawerContent from './DrawerComponents/DrawerContent';
import DrawerHome from './DrawerComponents/DrawerHome';
const Drawer = createDrawerNavigator();
export default class DrawerScreens extends React.Component {
render() {
return (
<Drawer.Navigator
drawerContent={() => (
<DrawerContent navigation={this.props.navigation} />
)}>
<Drawer.Screen name="DrawHome" component={DrawerHome} />
</Drawer.Navigator>
);
}
}
Here's my TabNavigator which is not working:
import React, { Component } from "react";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import DrawerHome from "./DrawerHome";
import Bookmarks from "./Bookmarks";
export default class TabComp extends Component {
render() {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: "#e91e63",
activeTintColor: "red",
inactiveTintColor: "grey",
style: {
backgroundColor: "white",
borderTopColor: "red"
},
labelStyle: {
fontSize: 12,
fontWeight: "normal"
},
indicatorStyle: {
borderBottomColor: "red",
borderBottomWidth: 4
}
}}
>
<Tab.Screen name="Home" component={DrawerHome} />
<Tab.Screen name="Bookmarks" component={Bookmarks} />
</Tab.Navigator>
);
}
}
It should be visible in my DrawerHome screens but not working
I don't know exactly what your HomePage component looks like, but it could look something like this with a button that navigates to your DrawerScreens screen:
const HomePage = ({navigation}) => {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Feed Screen</Text>
<Button
title="Go to DrawerScreens"
onPress={() => navigation.navigate('DrawerScreens')}
/>
</View>
);
};
The important thing I changed in your DrawerScreens component is that its screen is your TabComp component:
class DrawerScreens extends React.Component {
render() {
return (
<Drawer.Navigator
drawerContent={() => (
<DrawerContent navigation={this.props.navigation} />
)}>
<Drawer.Screen name="Tab" component={TabComp} />
</Drawer.Navigator>
);
}
}
The TabComp component itself can stay the same.
Then inside your DrawerHome component you can trigger your drawer using navigation.openDrawer().
const DrawerHome = ({navigation}) => {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Feed Screen</Text>
<Button title="Open Drawer" onPress={() => navigation.openDrawer()} />
</View>
);
};
This way you can show your tabs and your drawer at the same time.