undefined is not an object (evaluating this.props.navigation.dispatch) - react-native

I'm trying to use this.props.navigation.dispatch(DrawerActions.toggleDrawer()) in the following code but it takes this.props.navigation.dispatch as undefined.
My code:
//...imports
//set the function drawer inside a bottom tab navigator (works fine)
drawer = () => {
return(
<Drawer.Navigator>
<Drawer.Screen name="first" component={firstScreen} />
<Drawer.Screen name="second" children={this.TopTabStack} />
</Drawer.Navigator>
)
}
TopTab = () => {
return(
<MaterialTopTabs.Navigator
initialRouteName="third"
>
<MaterialTopTabs.Screen name="third" component={thirdScreen} />
<MaterialTopTabs.Screen name="fourth" component={fourthScreen} />
</MaterialTopTabs.Navigator>
)
}
TopTabStack = () => {
return(
<Stack.Navigator>
<Stack.Screen name="second" children={this.TopTab} options={{
headerRight: this.TopTabRightStack
}} />
</Stack.Navigator>
)
}
TopTabRightStack = () => {
return(
<View>
<TouchableWithoutFeedback onPress={async () => {this.props.navigation.dispatch(DrawerActions.toggleDrawer())}}>
<Ionicons name="ios-menu" size={26} />
</TouchableWithoutFeedback>
</View>
)
}

As you are using the Functional component so there is no need of using this, remove it from the given code, and run again.
drawer = () => {
return(
<Drawer.Navigator>
<Drawer.Screen name="first" component={firstScreen} />
<Drawer.Screen name="second" children={TopTabStack} />
</Drawer.Navigator>
)
}
TopTab = () => {
return(
<MaterialTopTabs.Navigator
initialRouteName="third"
>
<MaterialTopTabs.Screen name="third" component={thirdScreen} />
<MaterialTopTabs.Screen name="fourth" component={fourthScreen} />
</MaterialTopTabs.Navigator>
)
}
TopTabStack = () => {
return(
<Stack.Navigator>
<Stack.Screen name="second" children={TopTab} options={{
headerRight: TopTabRightStack
}} />
</Stack.Navigator>
)
}
TopTabRightStack = ({navigation}) => {
return(
<View>
<TouchableWithoutFeedback onPress={async () = {navigation.dispatch(DrawerActions.toggleDrawer())}}>
<Ionicons name="ios-menu" size={26} />
</TouchableWithoutFeedback>
</View>
)
}

OK, got it:
//...imports
//set the function drawer inside a bottom tab navigator (works fine)
drawer = () => {
return(
<Drawer.Navigator>
<Drawer.Screen name="first" component={firstScreen} />
<Drawer.Screen name="second" children={this.TopTabStack} />
</Drawer.Navigator>
)
}
TopTab = () => {
return(
<MaterialTopTabs.Navigator
initialRouteName="third"
>
<MaterialTopTabs.Screen name="third" component={thirdScreen} />
<MaterialTopTabs.Screen name="fourth" component={fourthScreen} />
</MaterialTopTabs.Navigator>
)
}
TopTabStack = ({navigation) => {
return(
<Stack.Navigator>
<Stack.Screen name="second" children={this.TopTab} options={{
headerRight: () => (
<View>
<TouchableWithoutFeedback onPress={async () = {navigation.dispatch(DrawerActions.toggleDrawer())}}>
<Ionicons name="ios-menu" size={26} />
</TouchableWithoutFeedback>
</View>
),
}} />
</Stack.Navigator>
)
}

Related

How can i use the Icon component to toggle drawer in header left

App.js
function App() {
return (// Navigation container with stack order
<Provider store={store}>
<NavigationContainer>
<DrawerNavigator />
</NavigationContainer>
</Provider>
);
}
DrawerNavigator.js
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => {
return (
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: {marginVertical: 5},
}}
drawerContent={(props) => <CustomSidebarMenu {...props} />}>
<Drawer.Screen
name="Authentication"
options={{drawerLabel: 'Authentication'}}
component={AuthStackNavigator}
/>
<Drawer.Screen
name="Symptom Checker
"
options={{drawerLabel: 'Symptom Checker'}}
component={MainStackNavigator}
/>
<Drawer.Screen
name="Reset Password
"
options={{drawerLabel: 'Reset Password'}}
component={ResetStackNavigator}
/>
</Drawer.Navigator>
);
};
export default DrawerNavigator;
StackNavigator.js
const Stack = createStackNavigator();
const AuthStackNavigator=() => {
return(
<Stack.Navigator initialRouteName='Authentication'>
<Stack.Screen name="Login" component={Login} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}}/>
<Stack.Screen name="SignUp" component={Signup} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}}/>
</Stack.Navigator>
)
}
const ResetStackNavigator=() => {
return(
<Stack.Navigator initialRouteName='Authentication'>
<Stack.Screen name="Reset Password" component={Reset_Password} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}} />
</Stack.Navigator>
)
}
const MainStackNavigator = () => {
return (
<Stack.Navigator initialRouteName="SymptomChecker">
<Stack.Screen name="Symptom" component={Page1} options={{
title: 'Search Symptoms',headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
) //Set Header Title
}}/>
<Stack.Screen name='Diagnosis' component={Page2} options={{
title: 'Diagnosis', headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)//Set Header Tit
}}/>
<Stack.Screen name='Disease Component' component={DiseaseComponent} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}} />
<Stack.Screen name='Summary' component={Summary} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}} />
</Stack.Navigator>
);
}
export { MainStackNavigator, AuthStackNavigator, ResetStackNavigator }
I know to toggle drawer I will be using navigation.toggleDrawer(). The issue is i don't know how can i gain the navigation prop inside each of my stack navigators.
I would be glad to accept any advice.
..........................................................................................
You can use useNavigation:
import { useNavigation } from '#react-navigation/native';
const MainStackNavigator = () => {
const navigation = useNavigation();
return (
<Stack.Navigator initialRouteName="SymptomChecker">
<Stack.Screen name="Symptom" component={Page1} options={{
title: 'Search Symptoms',headerLeft: () => (
<Icon
onPress={()=>navigation.toggleDrawer()}
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
) //Set Header Title
}}/>
<Stack.Screen name='Diagnosis' component={Page2} options={{
title: 'Diagnosis', headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)//Set Header Tit
}}/>
<Stack.Screen name='Disease Component' component={DiseaseComponent} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}} />
<Stack.Screen name='Summary' component={Summary} options={{
headerLeft: () => (
<Icon
name='ei-navicon'
type='evilicon'
color='#517fa4'
/>
)
}} />
</Stack.Navigator>

React has detected a change in the order of Hooks called by StackNavigator

I'm using StackNavigator, inside TabNavigator, inside Drawer Navigator.
Trying to redirect to nested Stacks but returns error.
Warning: React has detected a change in the order of Hooks called by StackNavigator. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks:
TypeError: undefined is not an object (evaluating 'prevDeps.length')
What's wront with that?
Why it doesnt redirect to stack.screen below main screen?
my redirect:
<TouchableOpacity style={styles.accessButton} onPress={() => navigation.navigate('Home', {
screen: 'Events'
})}>
My main.js (navigator)
return (
<NavigationContainer theme={NavigationTheme} ref={navigationRef}>
<StatusBar barStyle={darkMode ? 'light-content' : 'dark-content'} />
<Drawer.Navigator
drawerStyle={{ width: '100%' }}
drawerContent={(props) => <DrawerContent {...props} />}
>
<Drawer.Screen name="Startup" component={IndexStartupContainer} />
{isApplicationLoaded && BeforeLogin != null && (
<Drawer.Screen name="Main" component={BeforeLogin} />
)}
</Drawer.Navigator>
</NavigationContainer>
)
my tabbar navigator:
return (
<Tab.Navigator tabBarOptions={{showLabel: false}} lazy>
<Tab.Screen name="Home" component={HomeNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="home" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="SearchNavigator" component={SearchNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="search1" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="FAQNavigator" component={FAQNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="questioncircleo" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="ContactNavigator" component={ContactNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<Feather name="phone" size={39} color={colors.text} />
);
},
}}
/>
</Tab.Navigator>
)
and my HomeNavigator:
const HomeNavigator = ({ navigation }) => {
const Stack = createStackNavigator()
const { t } = useTranslation()
return (
<Stack.Navigator>
<Stack.Screen
options={headerStyle_1}
name='Index'
title={t('title.homepage')}
component={HomepageController}
/>
<Stack.Screen
options={headerStyle_1}
name='Events'
title={t('title.events')}
component={EventsController}
/>
</Stack.Navigator>
)
}

How to use props.navigation.closeDrawer() inside a CustomDrawerContent?(React Native)("#react-navigation/drawer": "^5.11.4")

My code for the current scenario is as follows:
function DrawerNavigation(props) {
return (
<DrawerContentScrollView {...props}>
<TouchableOpacity
style={styles.colseIconContainer}
onPress={() => props.navigation.closeDrawer()}>
<IconButton
icon={({size}) => (
<Image
source={require('../../../resource/images/CloseIcon.png')}
style={{width: size, height: size}}
/>
)}
size={40}
/>
</TouchableOpacity>
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
export default function MyDrawer(props) {
return (
<Drawer.Navigator
drawerPosition="right"
drawerContent={() => <DrawerNavigation {...props} />}
drawerStyle={styles.drawerStyle}>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{swipeEnabled: true}}
initialParams={props.navigation}
/>
<Drawer.Screen name="Notifications" component={CommonUserComponent} />
</Drawer.Navigator>
);
}
The error is undefined is not an object (evaluating 'props.naviagtion.closeDrawer')
Is there any way?? To make it work!!
Thank You !!
replace this
drawerContent={() => <DrawerNavigation {...props} />}
with this
drawerContent={(props) => <DrawerNavigation {...props} />}

How can I add navigation in the navigation header?

I'm trying to create a button for navigating to "CreateScreen", the button is placed in the header so I wrote it inside <NavigationContainer> as the documentation suggested, but it seems I don't have access to navigation, I don't actually need it inside NavigationContainer, so if you have other suggestions for implementing(for example, implementing the button inside the component) it will be great.
That's What I'm trying to accomplish(part of app.js)
headerRight: () => {
return <TouchableOpacity>
<Feather name="plus" size={30} onPress={() => navigation.navigate('Create')} />
</TouchableOpacity>
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Index">
<Stack.Screen
name="Index"
component={IndexScreen}
options={{
title: 'Home',
headerRight: () => {
return (
<TouchableOpacity>
<Feather
name="plus"
size={30}
onPress={
() => navigation.navigate('Create')
//Thats what Im trying to accomplish
}
/>
</TouchableOpacity>
);
},
}}
/>
<Stack.Screen name="Show" component={ShowScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
you can use the useNavigation hook to gain access to the navigation prop:
import { useNavigation } from '#react-navigation/native';
const navigation = useNavigation();
navigation.goBack();
source:
https://reactnavigation.org/docs/use-navigation/
In option will return navigation
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Index">
<Stack.Screen
name="Index"
component={IndexScreen}
//navigation<<<<<<<<<<<<<<<<<<<<<<<<<here
options={({navigation, route}) => ({
title: 'Home',
headerRight: () => {
return (
<TouchableOpacity>
<Feather
name="plus"
size={30}
onPress={() => navigation.navigate('Create')}
/>
</TouchableOpacity>
);
},
})}
/>
<Stack.Screen name="Show" component={ShowScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}

How to call toggleDrawer in React Navigation 5

I got a React-Navigation 5 drawer menu working using gesture, but I also want to add an icon on the right side of the header to toggle the drawer menu.
I have the navigation setup in my App.js like this:
import {NavigationContainer, DrawerActions} from '#react-navigation/native';
//....... other imports
const HomeStack = createStackNavigator();
const HomeStackScreens = () => (
<HomeStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
onPress={() => DrawerActions.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
}}>
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
header:({scene, previous, navigation}) => {
return (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
}
}}
/>
<HomeStack.Screen name="Login" component={Login} />
<HomeStack.Screen name="Register" component={Register} />
</HomeStack.Navigator>
);
const ProfileStack = createStackNavigator();
const ProfileStackScreens = () => (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={Profile} />
</ProfileStack.Navigator>
);
const SettingStack = createStackNavigator();
const SettingStackScreens = () => (
<SettingStack.Navigator>
<SettingStack.Screen name="Profile" component={Profile} />
</SettingStack.Navigator>
);
const Drawer = createDrawerNavigator();
const DrawerScreens = () => (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStackScreens} />
<Drawer.Screen name="Profile" component={ProfileStackScreens} />
<Drawer.Screen name="Settings" component={SetttingStackScreens} />
</Drawer.Navigator>
);
class MyApp extends React.Component {
render() {
return (
<NavigationContainer>
<DrawerScreens />
</NavigationContainer>
);
}
}
export default MyApp;
All my others screen are in the form "export default class ScreenName extends React.Component". They are imported in App.js to setup the navigation. The initial screen is Home. The icon is showing correctly on the right side of the header. Calling "DrawerActions.toggleDrawer()" directly does nothing.
I tried "this.props.navigation.toggleDrawer()", and it throws error because "this.props" is undefined.
How can I invoke toggleDrawer() with such a navigation setup? Any help is really appreciated!
Here is the final solution I come up with that requires minimal changes to my original code. The key is to receive "navigation" in screenOptions or options, then I can call navigation methods in the children of screenOptions/options.
<HomeStack.Navigator
screenOptions={({navigation}) => ({
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
style={{paddingRight: 8}}
onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
})}>