when I'm using DrawerItemList the app crashes - react-native

I'm trying to create a drawer menu using react navigation. I want to use a custom DrawerContent, and when I'm using the the app crashes with this error: "undefined is not an object (evaluating 'state.routes')". If I comment this specific line the app just run.
This is my DrawerContent:
import {
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from "#react-navigation/drawer";
import React from "react";
import { Text, View, StyleSheet } from "react-native";
export default function DrawerContent(props) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView
{...props}
contentContainerStyle={{ backgroundColor: "#000" }}
>
<DrawerItemList {...props} />
</DrawerContentScrollView>
</View>
);
}
This is my App.js(where the navigation is):
import React from "react";
import Home from "./src/screens/Home.js";
import { NavigationContainer } from "#react-navigation/native";
import { createDrawerNavigator } from "#react-navigation/drawer";
import DrawerContent from "./src/components/DrawerContent.js";
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator
drawerContent={() => <DrawerContent />}
initialRouteName="Home"
>
<Drawer.Screen
options={{ headerShown: false }}
name="Home"
component={Home}
></Drawer.Screen>
</Drawer.Navigator>
</NavigationContainer>
);

You're expecting DrawerItemList to receive a full set of props from Drawer.Navigator, but you're passing it to Drawer.Navigator wrapped in a function that discards all the props it receives:
<Drawer.Navigator
drawerContent={() => <DrawerContent />} // <-- no props passed to DrawerContent
initialRouteName="Home"
>
You need to pass through all props:
<Drawer.Navigator
drawerContent={(props) => <DrawerContent {...props} />} // <-- pass in the props
initialRouteName="Home"
>
Note that you might think you can just pass in the function component to the prop, like this, which looks functionally identical to the above:
<Drawer.Navigator
drawerContent={DrawerContent} // <-- will fail with "rules of hooks" errors
initialRouteName="Home"
>
...but this will fail with "Invalid hook call" errors if it's a functional component that contains hooks, because drawerContent prop treats the passed-in function as a render function, not a function component.

I tried every possible way to solve this error but at last just after restarting my computer i solved the error. Hope it works for you also

Related

Open Drawer when tapped on DrawerNavigator header button

I am trying to call openDrawer option from header of DrawerNavigation but the navigation prop does not contain openDrawer function.
import React from 'react';
import {View, TouchableOpacity} from 'react-native';
import {createDrawerNavigator} from '#react-navigation/drawer';
import Icon from 'react-native-vector-icons/Ionicons';
import {dimensions} from '../../constants/utils';
import CustomDrawerContent from './components/CustomDrawerContent';
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => {
screenOptionsProps = {
screenOptions: {
headerLeft: props => (
<View>
<TouchableOpacity onPress={() => navigation.openDrawer()}>
<Icon
name="reorder-three-sharp"
size={dimensions.width * 0.08}
{...props}
/>
</TouchableOpacity>
</View>
),
},
};
return (
<Drawer.Navigator
{...screenOptionsProps}
drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Dashboard" component={Dashboard} />
</Drawer.Navigator>
);
};
export default DrawerNavigator;
Whenever the Icon is being tapped drawer should be opened but navigation prop is not receiving anything and while consoling the navigation prop getting undefined as value. The props passed in drawerContent has openDrawer() method with in it but how to use it for screenOptions.
You can try "props.navigation.openDrawer()" or "props.navigation.toggleDrawer()"
headerLeft: props => (
<View>
<TouchableOpacity onPress={() =>
props.navigation.openDrawer()}>
<Icon
name="reorder-three-sharp"
size={dimensions.width * 0.08}
{...props}
/>
</TouchableOpacity>
</View>
),
Working on single time but when I return after to home screen it does not receive openDrawer() and closeDrawer() in props.navigation
For opening drawer navigation, finally i found the solution in the navigation props reference https://reactnavigation.org/docs/navigation-prop/. For anybody who got stuck with similar problem, it might be helpful.
So for the above problem i used useNavigation hook from #react-navigation/native which provides navigation object which can be further used for calling the openDrawer() method.
import React from 'react';
import {View, TouchableOpacity} from 'react-native';
import {createDrawerNavigator} from '#react-navigation/drawer';
import Icon from 'react-native-vector-icons/Ionicons';
import {dimensions} from '../../constants/utils';
import { DrawerActions, useNavigation } from "#react-navigation/native";
import CustomDrawerContent from './components/CustomDrawerContent';
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => {
const navigation = useNavigation();
screenOptionsProps = {
screenOptions: {
headerLeft: props => (
<View>
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Icon
name="reorder-three-sharp"
size={dimensions.width * 0.08}
{...props}
/>
</TouchableOpacity>
</View>
),
},
};
return (
<Drawer.Navigator
{...screenOptionsProps}
drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="Dashboard" component={Dashboard} />
</Drawer.Navigator>
);
};
export default DrawerNavigator;

how fixed this issue? navigation.navigate is not a function

This error occurs while using navigation. I don't understand why you do that.
The above error occurs when trying to navigate from HomeScreen to SignUp Detail through navigation.
I've looked everywhere, but I'm asking because I can't find the answer.
This error occurs while using navigation. I don't understand why you do that.
The above error occurs when trying to navigate from HomeScreen to SignUp Detail through navigation.
I've looked everywhere, but I'm asking because I can't find the answer.
this code App.js
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import SignUp from "./components/signupdetail/signup";
import HomeScreen from "./components/homeScreen";
const Stack = createStackNavigator();
const App = () => {
return (
<>
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="SignUp" component={SignUp} /> //my problem
</Stack.Navigator>
</NavigationContainer>
</>
);
};
export default App;
this code Homescreen
import Login from "./loginScreen/login";
import ButtonComponent from "./loginScreen/button";
import LostPassword from "./loginScreen/lostpassword";
import SocialLogin from "./loginScreen/sociallogin";
import SignUp from "./loginScreen/signup";
const HomeScreen = (props) => {
return (
<>
<SafeAreaView style={styles.container}>
<Text style={styles.header}>everywear</Text>
</SafeAreaView>
<View>
<Login />
<ButtonComponent />
<LostPassword />
<SocialLogin />
<SignUp navigation={props} />
</View>
</>
);
};
export default HomeScreen;
this code signup
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
const SignUp = (props) => {
const { navigation } = props;
return (
<>
<View style={styles.container}>
<Text style={styles.text}>혹시 처음이신가요?</Text>
<TouchableHighlight
onPress={() => {
navigation.navigate("SignUp");
}}
underlayColor="gray"
style={styles.button}
>
<>
<Text style={styles.signuptext}>회원가입</Text>
</>
</TouchableHighlight>
</View>
</>
);
};
export default SignUp;
There are different ways to fix this issue.
Easiest one would be to change like below
<SignUp navigation={props.navigation} />
This will pass the navigation prop correctly and the rest of the code would work as expected.
the useNavigation hook
you can use the hook like below
const SignUp = (props) => {
const navigation = useNavigation();
then no need to pass the prop from the parent.

React DrawerNavigation Is Not Working (Nothing Happens) While I Drag To Open Side Menu

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',
},
});

Bottom tab bar should not occur anywhere but only on the first initial screen that renders via Webview in React Native

I have a webview component in my project, where the flow being =>
The bottomTabBar opens the initial screen of the url that is given to Webview source prop, which should remain, when any link is clicked on the webview and it moves to another screen, the bottomtabbar should not come up.
Below is my WebviewScreen code :
import React, {Component} from 'react';
import {WebView} from 'react-native-webview';
import {View, SafeAreaView, ActivityIndicator} from 'react-native';
export default class ConsultationHomeScreen extends Component {
renderLoadingView = () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size="large" />
</View>
);
};
render() {
const {url} = this.props.route.params;
return (
<SafeAreaView style={{flex: 1}}>
<WebView
source={{uri: url}}
renderLoading={this.renderLoadingView}
startInLoadingState={true}
ref={(ref) => {
this.webview = ref;
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
this.webview.stopLoading();
}
}}
/>
</SafeAreaView>
);
}
}
And Appnavigation.js
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import LoginScreen from '../screens/authentication/LoginScreen';
import OtpScreen from '../screens/authentication/OtpScreen';
import AddChild from '../screens/Child/AddChild';
import AcceptInviteScreen from '../screens/AcceptInviteScreen';
import ConsultationHomeScreen from '../screens/ConsultationHomeScreen';
import HomeScreen from '../screens/HomeScreen/HomeScreen';
import PlansScreen from '../screens/PlansScreen';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function BottomTabBar() {
return (
<Tab.Navigator
lazy={false}
tabBarOptions={{
labelStyle: {
color: '#FF1493',
fontSize: 15,
},
}}>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: () => {
<MaterialIcon name="home" color="#FF1493" size={20} />;
},
}}
/>
<Tab.Screen
name="Consult"
component={ConsultationHomeScreen}
initialParams={{
url: 'some link',
}}
/>
<Tab.Screen name="Plans" component={PlansScreen} />
</Tab.Navigator>
);
}
export default function AppNavigation() {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none">
<Stack.Screen name="login" component={LoginScreen} />
<Stack.Screen name="otp" component={OtpScreen} />
<Stack.Screen name="addchild" component={AddChild} />
<Stack.Screen
name="acceptinvitescreen"
component={AcceptInviteScreen}
/>
<Stack.Screen name="home" component={BottomTabBar} />
</Stack.Navigator>
</NavigationContainer>
);
}
However, am unable to remove the bottomtabbar,could anyone please suggest how should I implement this behaviour?
Step1-> Webview initial screen renders and has bottomtabtabr
Step2-> Link clicked on the initial screen and navigates to next screen handled by web source
Step3->Bottom tab bar should not occur anywhere but only on the first initial screen
Please,any suggestion would be appreciated and let me know if anything else is required for better understanding.
I tested this modification in your source code and it works like a charm.
GIT difference in WebviewScreen.js :
## -23,6 +23,7 ## export default class ConsultationHomeScreen extends Component {
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
+ this.props.navigation.setOptions({ tabBarVisible: false });
this.webview.stopLoading();
}
}}
Let me know if you have any issue.

I keep getting errors that "navigation" is not defined

I am trying to create a login button that navigates to another page but I keep getting errors that "navigation" is not defined
here's the screenshot of the error:
screenshot here
screenshot here
that's the app component:
export default function App({navigation}) {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Image
source={logo}
style={styles.stretch}
/>
<Image
source={logo2}
style={styles.stretch2}
/>
<Button title="Login" style={[styles.buttonContainer, styles.loginButton,styles.top]} onPress={() => navigation.navigate("Details")} >
<Text style={styles.loginText}>LOG IN</Text>
</Button>
<TouchableHighlight style={[styles.buttonContainer2, styles.loginButton2,styles.top2]} >
<Text style={styles.loginText2}>Register</Text>
</TouchableHighlight>
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
</NavigationContainer>
</View>
);
}
here I got stuck after using the navigation Ref method:
link here
there is no this.props in function components:
export default function App({navigation}) {
const { navigate } = this.props.navigation;
this should be
export default function App({navigation}) {
const { navigate } = navigation;
notice that you already destructured navigation from props in the function signature
Your App component is a React hook, so calling this.props won't work. You can just use navigation from your App's params.
The navigation prop is only available to components wrapped within your <NavigationContainer> component. You'll probably still get an error trying to call navigate from the App component since <NavigationContainer> is a child of it.
Your best bet is to only use the navigation prop on components within a <NavigationContainer> or accessing it like this based on the documentation:
https://reactnavigation.org/docs/navigating-without-navigation-prop
EDIT:
If you want to access navigation outside of the navigation container, you'll need a ref pointing to it.
import React, { useRef } from "react";
export default function App({}) {
const navigationRef = useRef(null)
// Then wherever you wanna call navigate you do this:
// () => navigationRef.current.navigate("Details")
// make sure you do a null check on navigationRef.current if you want to be extra safe
return (
<NavigationContainer ref={navigationRef}>
....
</NavigationContainer>
)
}