not able to logging out from the app in react native? - reactjs

i am working on a react native project using redux. i have one stack navigator and one drawer navigator.
i am not able to logout from the app. i want to change store value while logging out. when i am dispatching the action from the logout onPress. it throws error: props.dispatch is not a function. how do i call. i tried many ways it always throwing an error. and how to set all reducers value to intial state while logout? Thank you in advance
App.js
<RootStack.Navigator screenOptions={{
headerShown: false
}}>
{/* <StatusBar backgroundColor={isLoading ? '#000000' : '#F3F3F3'} /> */}
{this.props.data.splashScreen.loading ?
(<RootStack.Screen name={'SplashScreen'} component={SplashScreen} />) :
this.props.data.login.isAuthorized ?
(<RootStack.Screen name="MainNavigator" component={MainNavigator} />)
:
(
<RootStack.Screen name="Login" component={MainStack} />)}
</RootStack.Navigator>
splashScreen and login are reducer store value
MainNavigator.js
const GradientHeader = (props) => (
<View style={{ backgroundColor: "transparent" }}>
<LinearGradient
colors={["#6CCFF6", "#596AB2"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={
{
/* height: 128 */
/* height: Header.HEIGHT */
}
}
>
<Header {...props} />
</LinearGradient>
</View>
);
const DashboardStackScreen = ({ navigation }) => {
return (
<DashboardStack.Navigator
screenOptions={{
headerTitle: "Good Morning, John",
header: (props) => <GradientHeader {...props} />,
headerLeft: () => (
<TouchableOpacity onPress={navigation.openDrawer} style={{ padding: 20 }}>
<Image source={require("../assets/images/menu_bar.png")} style={{ width: 18, height: 12 }} />
</TouchableOpacity>
),
headerTransparent: true,
headerStyle: {
backgroundColor: "transparent",
},
headerTintColor: "#fff",
headerTitleStyle: { fontFamily: "OpenSans-SemiBold", fontSize: 20 },
}}
>
<DashboardStack.Screen name="Dashboard" component={Dashboard} />
</DashboardStack.Navigator>
);
};
export default ({ navigation }) => {
return (
<Drawer.Navigator
initialRouteName="Dashboard"
drawerContent={(props) => <DrawerContent {...props} />}
hideStatusBar={false}
focused={true}
labelStyle={{ fontSize: 14, fontFamily: "OpenSans-SemiBold" }}
drawerContentOptions={{ activeBackgroundColor: "#F1F1F1", activeTintColor: "#000000", inactiveTintColor: "#818181", itemStyle: { marginLeft: 0, paddingHorizontal: 10, width: "100%", borderRadius: 0 } }}
>
<Drawer.Screen
name="Dashboard"
component={DashboardStackScreen}
options={{
drawerIcon: ({ focused, size }) => <Image source={require("../assets/images/dashboard.png")} style={{ height: 17.78, width: 16 }} resizeMode="contain" />,
}}
/>
<Drawer.Screen
name="My Profile"
component={MyProfileStackScreen}
options={{
drawerIcon: ({ focused, size }) => <Image source={require("../assets/images/profile.png")} style={{ height: 16, width: 16 }} resizeMode="contain" />,
}}
/>
</Drawer.Navigator>
);
};
DrawerContent.js
import { resetData } from "../Storage/Storage";
export function DrawerContent(props) {
return (
<SafeAreaView style={styles.baseContainer}>
<KeyboardAvoidingView behaviour="padding" style={styles.baseContainer}>
<TouchableWithoutFeedback style={styles.baseContainer} onPress={Keyboard.dismiss}>
<View style={styles.baseContainer}>
<TouchableOpacity
style={{ flex: 2, alignItems: "center", justifyContent: "center" }}
onPress={() => {
props.navigation.navigate("Dashboard");
}}
>
<Image source={require("../assets/images/MJB_Logo.png")} style={{ width: 197, height: 59 }} />
</TouchableOpacity>
<View style={{ flex: 5 }}>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem
labelStyle={{ fontSize: 14, fontFamily: "OpenSans-SemiBold" }}
activeBackgroundColor="#F1F1F1"
activeTintColor="#000000"
inactiveTintColor="#818181"
label="Logout"
icon={({ focused, color, size }) => {
return <Image source={require("../assets/images/logout.png")} style={{ height: 14.36, width: 14.36 }} resizeMode="contain" />;
}}
onPress={() => resetData()}
/>
</DrawerContentScrollView>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
Storage.js
export const resetData = async () => {
try {
//await AsyncStorage.removeItem('isRemembered')
await AsyncStorage.removeItem("userDetails");
} catch (e) {
// saving error
}
};

Related

useEffect not firing on state update

I am updating some state with useState() in my react native component. Once I have that state set I want to save the details to the server, so I have set that up in an useEffect() hook. To be clear, the setting of the state IS working, and I see the value print to the screen.
However, what I'm noticing is, even though I've set note as a dependency in the dependency array of the useEffect() hook, the function never fires when the state updates. What am I missing here?
const [note, setNote] = useState('');
const dispatch = useDispatch();
useEffect(() => {
if (note) {
console.log('updating note...');
dispatch(updateNote(props.client.id, note));
}
}, [note]);
FYI, I am updating the state inside a TextInput, like so (I had to use onBlur to avoid the issue of react loosing focus on the first character type because I am passing a component within screenOptions of a TabNavigator):
<TextInput
key='note'
style={{
color: '#fff',
fontSize: 16,
width: '100%',
textAlign: 'center',
}}
placeholder='Tap here to share something...'
placeholderTextColor={styles.colors.textPlaceholder}
maxLength={50}
onBlur={(text) => setNote(text)}
defaultValue={note || props?.client?.note?.value}
/>
As I mentioned, this has been a tricky situation because I had to get around react's loss of focus when I rely on onChangeText() or onChange(). I am passing in a CustomHeader - which is a function inside the parent, to a TabNavigator within screenOptions like so:
screenOptions={{
headerShown: true,
headerStyle: {
backgroundColor: Colors.primary,
elevation: 0,
shadowOpacity: 0,
shadowColor: 'transparent',
height: 170,
},
key: 'patient-tab',
headerShadowVisible: false,
tabBarStyle: { backgroundColor: Colors.primary },
headerTintColor: Colors.light,
headerTitle: (props) => <CustomHeader {...props} />, // Passed in here
tabBarActiveTintColor: Colors.light,
tabBarInactiveTintColor: Colors.lightInactive,
tabBarActiveBackgroundColor: Colors.primary,
tabBarInactiveBackgroundColor: Colors.primary,
}}
The full code looks like this:
export const ClientBottomTabNavigator = (props) => {
const [note, setNote] = useState('');
const dispatch = useDispatch();
useEffect(() => {
if (props.client.id && note) {
console.log('updating note...');
dispatch(updateNote(props.client.id, note));
}
}, [props.client.id, note]);
const CustomHeader = () => {
return (
<View>
<View style={{ width: '100%', flexDirection: 'row', justifyContent: 'space-between', marginBottom: 6 }}>
<Feather
name='chevron-left'
size={24}
onPress={() => props.navigation.goBack()}
color={styles.colors.textInverse}
style={{ justifySelf: 'flex-start', alignSelf: 'flex-start', width: '32%', marginBottom: 6 }}
/>
<Text
style={{
color: '#fff',
fontSize: 18,
alignSelf: 'center',
justifySelf: 'center',
fontWeight: 'bold',
}}
>
{props?.client?.firstName} {props?.client?.lastName}
</Text>
<Feather
name='' // Leave this blank
style={{ justifySelf: 'flex-end', alignSelf: 'flex-end', width: '32%' }}
/>
</View>
<View style={{ alignItems: 'center', marginBottom: 6 }}>
<Text style={{ color: '#fff', fontSize: 18, marginBottom: 6 }}>
{convertDiscipline(props?.client?.discipline)}
</Text>
<View>
<TextInput
key='note'
style={{
color: '#fff',
fontSize: 16,
width: '100%',
textAlign: 'center',
}}
placeholder='Tap here to share something…’
placeholderTextColor={styles.colors.textPlaceholder}
maxLength={50}
onBlur={(text) => setNote(text)}
defaultValue={note || props?.client?.note?.value}
/>
</View>
</View>
</View>
);
};
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator
screenOptions={{
headerShown: true,
headerStyle: {
backgroundColor: Colors.primary,
elevation: 0,
shadowOpacity: 0,
shadowColor: 'transparent',
height: 170,
},
key: 'client-tab',
headerShadowVisible: false,
tabBarStyle: { backgroundColor: Colors.primary },
headerTintColor: Colors.light,
headerTitle: (props) => <CustomHeader {...props} />, // Passed in here
tabBarActiveTintColor: Colors.light,
tabBarInactiveTintColor: Colors.lightInactive,
tabBarActiveBackgroundColor: Colors.primary,
tabBarInactiveBackgroundColor: Colors.primary,
}}
initialRouteName={'Visits'}
>
<Tab.Screen
name='Visits'
component={VisitsTab}
options={{
tabBarLabel: 'VISITS',
tabBarIcon: ({ color, size }) => <FontAwesome name='street-view' color={color} size={size} />,
}}
/>
<Tab.Screen
name='Chart'
component={ChartTab}
options={{
tabBarLabel: 'CHARTS',
tabBarIcon: ({ color, size }) => <FontAwesome name='id-badge' color={color} size={size} />,
}}
/>
<Tab.Screen
name='Goals'
component={GoalsTab}
options={{
tabBarLabel: 'EDIT GOALS',
tabBarIcon: ({ color, size }) => <FontAwesome name='trophy' color={color} size={size} />,
}}
/>
</Tab.Navigator>
);
};
See here https://playcode.io/1106437, it works, but you have onBlur, you need to blur to trigger the action, maybe you need to use onChangeText insted.

React Native Bottom tab bar jump on every load

i have the exact same problem like on issue:
React Native header / bottom tabbar jumping on first app load
On every load the bottom bar jumps up and down for unknown reason. I wrapped the root app in SafeAreaProvider, i wrapped my screens in SafeAreaView and still the same thing happens.
Here is my code:
Root App:
const App = () => {
return (
<SafeAreaProvider>
<StatusBar backgroundColor="#01497C" />
<NavigationContainer>
<Stack.Navigator
initialRouteName="AuthLoadingScreen"
screenOptions={{headerShown: false}}>
<Stack.Screen
name="AuthLoadingScreen"
component={AuthLoadingScreen}
/>
<Stack.Screen name="Home" component={Tabs} />
<Stack.Screen name="QuizScreen" component={QuizScreen} />
<Stack.Screen name="QuizReviewScreen" component={QuizReviewScreen} />
<Stack.Screen name="QuizEndScreen" component={QuizEndScreen} />
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
};
Tabs:
const Tabs = () => {
const TabBarCustom = ({children, onPress}) => {
return (
<TouchableOpacity
style={{top: -10, justifyContent: 'center', alignItems: 'center'}}
onPress={onPress}
activeOpacity={1}>
<LinearGradient
style={{
width: 70,
height: 70,
borderRadius: 35,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
}}
colors={['#01497C', '#89C2D9']}>
{children}
</LinearGradient>
</TouchableOpacity>
);
};
return (
<Tab.Navigator
tabBarOptions={{
showLabel: false,
style: {
height: 60,
},
}}>
<Tab.Screen
name="Quizzes"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="apps-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Quizzes
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Flashcards"
component={FlashCardsScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="copy-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Flashcards
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Import"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Icon
name="plus"
color={focused ? '#A9D6E5' : 'white'}
size={42}
/>
</View>
),
tabBarButton: props => <TabBarCustom {...props} />,
}}
/>
<Tab.Screen
name="Account"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="person-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Account
</Text>
</View>
),
}}
/>
<Tab.Screen
name="About"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="search"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Search
</Text>
</View>
),
}}
/>
</Tab.Navigator>
);
};
The issue happens every time tabs get loaded.
I had the same issue, in my case I was using Custom StatusBar in different screens with different props. The issue was I wasn't using translucent prop in all screen StatusBar. Using translucent in all screen StatusBar fixed the problem. Give me a thumbs up if it solve your problem.
I use MaterialCommunityIcons for tab icons so,
I sove this issue with
useLayoutEffect(() => {
async function loadIcons() {
setIsLoading(true);
await MaterialCommunityIcons.loadFont();
setIsLoading(false);
}
loadIcons();
}, []);
if (isLoading) {
return <></>;
}
Why useLayouEffect?
The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint. read more

React Native, Custom DrawerContent navigator issue

I have a custom DrawerContent component and I am unable to navigate to a screen from it using navigator.navigate('DrawerHelp').
I am still getting this error and I really have no idea how to fix it.
I am trying to navigate from the Help button to its own component called DrawerHelp.
issue The action 'NAVIGATE' with payload {"name":"DrawerHelp"} was not handled by any navigator
This is my code below.
function DrawerComponent() {
return (
<Drawer.Navigator
drawerContentOptions={{activeBackgroundColor: '#efefef', activeTintColor: '#000000'}}
initialRouteName="Tabs"
drawerStyle={{ backgroundColor:'#ffffff', width:'85%', paddingBottom: 50 }}
drawerContent={
props => ( <CustomDrawerContent {...props} /> )
}>
<Drawer.Screen name="Dashboard" component={Tabs} options={{
drawerIcon: config => <Ionicons name={'ios-home'} size={18} color={'#444'} headerTitle="AAA" />,
}} />
<Drawer.Screen name="Help" component={DrawerHelp}
options={{
drawerIcon: config => <Ionicons name={'ios-people-circle-outline'} size={18} color={'#444'}/>,
}}
/>
</Drawer.Navigator>
);
}
export function CustomDrawerContent (props) {
const [ tabs, setTabs ] = useState([
{
name: 'Help',
icon: 'ios-call',
borderColor: '#e7c53f',
backgroundColor: '#fff',
color: '#e7c53f',
fontWeight: '500'
},{
name: 'Share',
icon: 'ios-megaphone',
borderColor: '#e7c53f',
backgroundColor: '#fff',
color: '#e7c53f',
fontWeight: '500'
},{
name: 'Logout',
icon: 'ios-log-out',
borderColor: '#e7c53f',
backgroundColor: '#fff',
color: '#e7c53f',
fontWeight: '500'
}
]);
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<View style={{ padding: 15 }}>
<View style={{
flexDirection: 'row',
justifyContent: 'space-between',
height: 50,
alignItems: 'center'
}}>
{
tabs.map((tab) => {
return (
<TouchableOpacity
key={tab.name}
style={{
height: '100%',
flex: .32,
alignItems: 'center',
borderWidth: .5,
borderColor: tab.borderColor,
backgroundColor: tab.backgroundColor,
borderRadius: 10,
flexDirection: 'row',
justifyContent: 'space-evenly'
}}
onPress={() => {
if(tab.name == 'Logout') {
// navigation.toggleDrawer();
}
if(tab.name == 'Share') {
// onShare();
}
if(tab.name == 'Help') {
props.navigation.navigate('DrawerHelp');
}
}}>
<Ionicons name={tab.icon} size={18} style={{ color: tab.color }} />
<Text style={{ color: tab.color, fontWeight: tab.fontWeight }}>{trans(tab.name, cntx.lang)}</Text>
</TouchableOpacity>
)
})
}
</View>
</View>
</DrawerContentScrollView>
);
}
It is not working because you have defined DrawerComponent with name 'Help'
<Drawer.Screen name="Help" component={DrawerHelp}
options={{drawerIcon: config => <Ionicons name={'ios-people-circle-outline'} size={18} color={'#444'}/>
if(tab.name == 'Help') {
props.navigation.navigate('DrawerHelp'); <== Change here to Help not DrawerHelp
}

How to access the nested navigator and how to setup properly the authentication flow

I'm quite new on react native this is just a practice project. now I have module regarding on authentication of users and how will navigate dashboard via conditioning the set asyncstorage item if the storage filtered that this storage has true value the user who access will directly move his/her screen to the AuthenticatedDriverScreen.
My Question:
How to navigate in a nested navigator?
How to call the getItem storage item on Navigator Screens?
My Error:
The action 'NAVIGATE' with payload {"name":"BindedScreenComponent","params":{"screen":"DriverDashboard"}} was not handled by any navigator.
Do you have a screen named 'BindedScreenComponent'?
I have already coded some functionality like Navigators Screen, Login Screen Etc. on the next paragraph I will share to you guys the code in every screens. I hope you will understand guys what I mean.
Navigator.JS
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const Bind = createStackNavigator();
const UnauthenticatedScreen = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Login"
component={Login}
options=
{{
headerShown: false,
}}
/>
<Stack.Screen
name="Registration"
component={Register}
options={{
headerStyle: {
backgroundColor: '#4ABDFF'
},
headerTitleStyle: {
color: '#fff',
},
headerTintColor: '#fff',
}}
/>
<Stack.Screen
name="Privacy"
component={PrivacyPolicy}
options={{
headerStyle: {
backgroundColor: '#4ABDFF'
},
headerTitleStyle: {
color: '#fff',
},
headerTitle: 'Privacy Policy',
headerTintColor: '#fff',
}}
/>
<Stack.Screen
name="RegistrationSuccess"
component={RegistrationSuccess}
options=
{{
headerShown: false,
}}
/>
<Stack.Screen
name="ForgotPassword"
component={ForgotPassword}
options={{
headerStyle: {
backgroundColor: '#4ABDFF'
},
headerTitleStyle: {
color: '#fff',
},
headerTitle: 'Forgot Password',
headerTintColor: '#fff',
}}
/>
</Stack.Navigator>
)
}
const BindedScreenComponent = () => {
return (
<Bind.Navigator>
<Bind.Screen
name="DriverDashboard"
component={DriverDashboard}
options={{
headerStyle: {
backgroundColor: '#4ABDFF',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
headerTitle: 'Driver Dashboard'
}}
/>
<Bind.Screen
name="DriverProfile"
component={DriverProfile}
options={{
headerStyle: {
backgroundColor: '#4ABDFF'
},
headerTitleStyle: {
color: '#fff',
},
headerTitle: 'Profile',
headerTintColor: '#fff',
}}
/>
</Bind.Navigator>
)
}
const AuthenticatedDriverScreen = () => {
return (
<Drawer.Navigator drawerContent={props => <CustomDriverDrawer {...props} />} initialRouteName="DriverDashboard">
<Drawer.Screen
name="DriverDashboard"
component={BindedScreenComponent}
options={
{
drawerLabel: 'Home',
drawerIcon: ({ focused, color, size }) => (
<Icon type="font-awesome" name="home" style={{ fontSize: size, color: color }} />
),
}
}
/>
</Drawer.Navigator>
)
}
class Navigator extends React.Component {
constructor(props) {
super(props);
this.state = {
phone_number:'',
password:''
}
}
render() {
const isLogin = false
// try {
// const value = await AsyncStorage.getItem('access_token');
// if (value !== null) console.log(value)
// } catch (error) { // Error retrieving data }
return (
<NavigationContainer>
{isLogin ? <AuthenticatedDriverScreen /> : <UnauthenticatedScreen />}
</NavigationContainer>
)
}
}
export default Navigator;
Login.JS
const UserInfo = {phone_number:'09361876184', password: '123456'}
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
phone_number:'',
password:''
}
}
LoginSubmitFunction = async () => {
const phone_number = this.state.phone_number;
const password = this.state.password;
if(UserInfo.phone_number === phone_number && UserInfo.password === password) {
await AsyncStorage.setItem('userToken', '1');
this.props.navigation.navigate('BindedScreenComponent',{screen:'DriverDashboard'});
}else {
alert('Username or Password is Incorrect!');
}
}
render() {
return (
<SafeAreaView style={[styles.container, { backgroundColor: '#ffff' }]}>
<StatusBar barStyle="dark-content" backgroundColor="#ffff" />
<ScrollView>
<View style={{ marginTop: 60 }}>
<Text style={{ fontSize: 25, fontWeight: 'bold' }}>LOGO</Text>
<Text style={{ fontSize: 20, fontWeight: 'bold', marginTop: 30 }}>Login your credential</Text>
</View>
<View style={{ marginTop: 30 }}>
<TextInput
onChangeText={(phone_number) => this.setState({phone_number})}
value={this.state.phone_number}
placeholder="+63"
keyboardType='numeric'
style={{ height: 50, borderRadius: 5, paddingLeft: 20, borderColor: '#EEEEEE', borderWidth: 1, backgroundColor: '#EEEEEE' }}
/>
<TextInput
onChangeText={(password) => this.setState({password})}
value={this.state.password}
placeholder="Password"
secureTextEntry={true}
style={{ marginTop: 20, borderRadius: 5, paddingLeft: 20, height: 50, borderColor: '#EEEEEE', borderWidth: 1, backgroundColor: '#EEEEEE' }}
/>
</View>
<View style={{ marginTop: 30 }}>
<TouchableOpacity
onPress={this.LoginSubmitFunction}
style={{ height: 70 }} >
<Text style={{ backgroundColor: '#4ABDFF', fontSize: 20, textAlign: 'center', padding: 10, borderRadius: 5, color: '#ffff' }}>Login</Text>
</TouchableOpacity>
</View>
<View style={{ marginTop: 0, alignItems: 'center' }}>
<Text onPress={() => this.props.navigation.navigate('ForgotPassword')} style={{ fontSize: 17 }}>Forgot Password?</Text>
<Text style={{ fontSize: 17, marginTop: 10 }}>Don't have an account yet? <Text style={{ textDecorationLine: 'underline', color: '#4ABDFF', fontWeight: 'bold' }} onPress={() => this.props.navigation.navigate('Registration')}>Register Here</Text></Text>
</View>
</ScrollView>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: { flex: 2, padding: 40 },
});
export default Login;
Output:
The action 'NAVIGATE' with payload {"name":"BindedScreenComponent","params":{"screen":"DriverDashboard"}} was not handled by any navigator.
Because your LoginScreen in UnauthenticatedScreen stack. But UnauthenticatedScreen not contain any screen has name "BindedScreenComponent".
With use isLogin variable to check login, You dont need use NAVIGATE.
await AsyncStorage.setItem('userToken', '1');
userToken is key, and has value is '1' in AsyncStorage.
In your Navigator.JS, You can call it:
const isLogin = await AsyncStorage.getItem('userToken') === '1'
if isLogin = true, it return AuthenticatedDriverScreen . And else, return UnauthenticatedScreen

React Navigation: passing parameters to a route: TyperError

I have a list of profiles on my Screen "NerdList" built using ListItems (react-native-element) and a Flatlist. When you click on a profile from the list, the app should navigate to the "Profile" screen and pass a test parameter with it.
NerdList Screen:
import React from "react";
import { withNavigation } from '#react-navigation/compat';
import { StyleSheet, FlatList} from "react-native";
import { ListItem } from "react-native-elements";
import nerdProfiles from '../constants/nerdProfiles';
import { Block, Text } from 'galio-framework';
import argonTheme from "../constants/Theme";
import { TouchableOpacity } from "react-native-gesture-handler";
class NerdList extends React.Component {
renderItem = ({item}) => (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Profile', {test: 'Hello'})}
>
<ListItem
title={
<Block>
<Text style={styles.names}>
{item.name}
</Text>
</Block>
}
subtitle={
<Block>
<Text style={styles.descriptions}>
{item.shortDescription}
</Text>
</Block>
}
leftAvatar={{ source: { uri: item.image } }}
bottomDivider
chevron
/>
</TouchableOpacity>
);
render() {
return (
<FlatList
data={nerdProfiles.bios}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
);
};
};
export default withNavigation(NerdList);
The navigation alone works, but when I try to pass a parameter, I receive a TypeError: undefined is not an object (evaluating '_ref3.route').
Here is the code I am using to receive the route on the "Profile" screen:
const {test} = route.params;
Full Profile Screen Code:
import React from "react";
import {
StyleSheet,
Dimensions,
ScrollView,
Image,
ImageBackground,
Platform
} from "react-native";
import { Block, Text, theme } from "galio-framework";
import { Button } from "../components";
import { Images, argonTheme } from "../constants";
import { HeaderHeight } from "../constants/utils";
import { FlatList, TouchableWithoutFeedback } from "react-native-gesture-handler";
import nerdProfiles from "../constants/nerdProfiles";
import ArticleCard from "../components/ArticleCard";
import VideoCard from "../components/VideoCard";
const { width, height } = Dimensions.get("screen");
const thumbMeasure = (width - 48 - 32) / 3;
//keyExtractor = (item, index) => index.toString()
class Profile extends React.Component {
renderVideoItem = ({item}) => {
return(
<Block style={{ marginRight: theme.SIZES.BASE }}>
<TouchableWithoutFeedback>
<VideoCard
item={item}
imageStyle={{ width: "auto", height: 94 }}
style={{ width: width / 3.75}}
/>
</TouchableWithoutFeedback>
</Block>
);
};
renderArticleItem = ({item}) => {
return(
<Block style={{ marginRight: theme.SIZES.BASE }}>
<TouchableWithoutFeedback>
<ArticleCard
item={item}
imageStyle={{ width: "auto", height: 94 }}
style={{ width: width / 3.75}}
/>
</TouchableWithoutFeedback>
</Block>
);
};
render() {
const { params } = this.props.navigation.state;
const test= params ? params.test: null;
return (
<Block flex style={styles.profile}>
<Block flex>
<ImageBackground
source={Images.ProfileBackground}
style={styles.profileContainer}
imageStyle={styles.profileBackground}
>
<ScrollView
showsVerticalScrollIndicator={false}
style={{ width, marginTop: "25%" }}
>
<Block flex style={styles.profileCard}>
<Block middle style={styles.avatarContainer}>
<Image
source={{uri: nerdProfiles.bios[0].image}}
style={styles.avatar}
/>
</Block>
<Block style={styles.info}>
<Block
middle
row
space="evenly"
style={{ marginTop: 20, paddingBottom: 24 }}
>
<Button
small
style={{ backgroundColor: argonTheme.COLORS.DEFAULT }}
>
FOLLOW
</Button>
</Block>
<Block row space="between">
<Block middle>
<Text
size={18}
color="#525F7F"
style={{ marginBottom: 4, fontFamily: 'open-sans-bold' }}
>
2K
</Text>
<Text style={{ fontFamily: 'open-sans-regular' }} size={12} color={argonTheme.COLORS.TEXT}>Followers</Text>
</Block>
<Block middle>
<Text
color="#525F7F"
size={18}
style={{ marginBottom: 4, fontFamily: 'open-sans-bold' }}
>
10
</Text>
{test}
<Text style={{ fontFamily: 'open-sans-regular' }} size={12} color={argonTheme.COLORS.TEXT}>Content</Text>
</Block>
</Block>
</Block>
<Block flex>
<Block middle style={styles.nameInfo}>
<Text style={{ fontFamily: 'open-sans-regular' }} size={28} color="#32325D">
{test}
</Text>
<Text size={16} color="#32325D" style={{ marginTop: 10, fontFamily: 'open-sans-light' }}>
{nerdProfiles.bios[0].location}
</Text>
</Block>
<Block style={styles.categories}>
<Button small>Math</Button>
<Button small>Finance</Button>
<Button small>Physics</Button>
</Block>
<Block middle style={{ marginTop: 30, marginBottom: 16 }}>
<Block style={styles.divider} />
</Block>
<Block middle>
<Text
size={16}
color="#525F7F"
style={{ textAlign: "center", fontFamily: 'open-sans-regular' }}
>
{nerdProfiles.bios[0].longDescription}
</Text>
<Button
color="transparent"
textStyle={{
color: "#233DD2",
fontWeight: "500",
fontSize: 16,
fontFamily: 'open-sans-regular'
}}
>
Show more
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Video Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block style={{ marginHorizontal: theme.SIZES.BASE }}>
<FlatList
style={styles.flatlist}
keyExtractor={this.keyExtractor}
data={nerdProfiles.bios[0].videos}
renderItem={this.renderVideoItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Articles Written
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block style={{ marginHorizontal: theme.SIZES.BASE }}>
<FlatList
style={styles.flatlist}
keyExtractor={this.keyExtractor}
data={nerdProfiles.bios[0].articles}
renderItem={this.renderArticleItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Podcast Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Live Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Academic Work
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
</Block>
</Block>
<Block style={{ marginBottom: 25 }}/>
</ScrollView>
</ImageBackground>
</Block>
</Block>
);
}
}
NerdList screen (first screen)
import React from "react";
import { Dimensions } from "react-native";
import { createStackNavigator } from "#react-navigation/stack";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
// screens
import Feed from "../screens/Feed";
// import Onboarding from "../screens/Onboarding";
import Pro from "../screens/Pro";
import Profile from "../screens/Profile";
import Register from "../screens/Register";
import Elements from "../screens/Elements";
import Articles from "../screens/Articles";
import Search from "../screens/Search";
import Cart from "../screens/Cart";
import NerdList from "../screens/NerdList";
// settings
import SettingsScreen from "../screens/Settings";
import AgreementScreen from "../screens/Agreement";
import PrivacyScreen from "../screens/Privacy";
import AboutScreen from "../screens/About";
import NotificationsScreen from "../screens/Notifications";
// Notifications
import PersonalNotifications from "../screens/PersonalNotifications";
import SystemNotifications from "../screens/SystemNotifications";
// drawer
import CustomDrawerContent from "./Menu";
// header for screens
import { Icon, Header } from "../components";
import { argonTheme, tabs } from "../constants";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
const { width } = Dimensions.get("screen");
export const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
function NotificationsStack() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color }) => {
let iconName;
if (route.name === "Personal") {
iconName = "user";
} else if (route.name === "System") {
iconName = "database";
} else if (route.name === "NerdList") {
iconName = "user"
}
// You can return any component that you like here!
return (
<Icon
name={iconName}
family="entypo"
size={22}
color={color}
style={{ marginTop: 10 }}
/>
);
}
})}
tabBarOptions={{
activeTintColor: argonTheme.COLORS.PRIMARY,
inactiveTintColor: "gray",
labelStyle: {
fontFamily: "open-sans-regular"
}
}}
>
<Tab.Screen name="Personal" component={PersonalNotifications} navigation />
<Tab.Screen name="System" component={SystemNotifications} />
<Tab.Screen name="NerdList" component={NerdList} />
</Tab.Navigator>
);
}
function BottomTabStack() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color }) => {
let iconName;
if (route.name === "Feed") {
iconName = "user";
} else if (route.name === "System") {
iconName = "database";
} else if (route.name === "NerdList") {
iconName = "user"
}
// You can return any component that you like here!
return (
<Icon
name={iconName}
family="entypo"
size={22}
color={color}
style={{ marginTop: 10 }}
/>
);
}
})}
tabBarOptions={{
activeTintColor: argonTheme.COLORS.PRIMARY,
inactiveTintColor: "gray",
labelStyle: {
fontFamily: "open-sans-regular"
}
}}
>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="System" component={SystemNotifications} />
<Tab.Screen name="NerdList" component={NerdList} />
</Tab.Navigator>
);
}
function ElementsStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Elements"
component={Elements}
options={{
header: ({ navigation, scene }) => (
<Header title="Elements" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function NerdListStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="NerdList"
component={NerdList}
options={{
header: ({ navigation, scene }) => (
<Header title="NerdList" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Profile"
component={Profile}
options={{
header: ({ navigation, scene }) => (
<Header
transparent
white
title="Profile"
navigation={navigation}
scene={scene}
back={true}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" },
headerTransparent: true
}}
/>
</Stack.Navigator>
);
}
function SettingsStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={{
header: ({ navigation, scene }) => (
<Header title="Settings" scene={scene} navigation={navigation} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Agreement"
component={AgreementScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Agreement"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Privacy"
component={PrivacyScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Privacy"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="About"
component={AboutScreen}
options={{
header: ({ navigation, scene }) => (
<Header back title="About" scene={scene} navigation={navigation} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="NotificationsSettings"
component={NotificationsScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Cart"
component={Cart}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Shopping Cart"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Notifications"
component={NotificationsStack}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function ArticlesStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Articles"
component={Articles}
options={{
header: ({ navigation, scene }) => (
<Header title="Articles" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function ProfileStack() {
return (
<Stack.Navigator initialRouteName="Profile" mode="card" headerMode="screen">
<Stack.Screen
name="Profile"
component={Profile}
options={{
header: ({ navigation, scene }) => (
<Header
transparent
white
title="Profile"
navigation={navigation}
scene={scene}
back={true}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" },
headerTransparent: true
}}
/>
<Stack.Screen
name="Cart"
component={Cart}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Shopping Cart"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" }
}}
/>
<Stack.Screen
name="Notifications"
component={NotificationsStack}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" }
}}
/>
</Stack.Navigator>
);
}
function FeedStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Feed"
component={BottomTabStack}
options={{
header: ({ navigation, scene }) => (
<Header
title="Feed"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Search"
component={Search}
options={{
header: ({ navigation, scene }) => (
<Header title="Search" back navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function AppStack() {
return (
<Drawer.Navigator
style={{ flex: 1 }}
drawerContent={props => <CustomDrawerContent {...props} />}
drawerStyle={{
backgroundColor: "white",
width: width * 0.8
}}
drawerContentOptions={{
activeTintcolor: "white",
inactiveTintColor: "#000",
activeBackgroundColor: "transparent",
itemStyle: {
width: width * 0.75,
backgroundColor: "transparent",
paddingVertical: 16,
paddingHorizonal: 12,
justifyContent: "center",
alignContent: "center",
alignItems: "center",
overflow: "hidden"
},
labelStyle: {
fontSize: 18,
marginLeft: 12,
fontWeight: "normal"
}
}}
initialRouteName="Feed"
>
<Drawer.Screen name="Feed" component={FeedStack} />
<Drawer.Screen name="Profile" component={ProfileStack} />
<Drawer.Screen name="Account" component={Register} />
<Drawer.Screen name="Elements" component={ElementsStack} />
<Drawer.Screen name="Articles" component={ArticlesStack} />
<Drawer.Screen name="Settings" component={SettingsStack} />
<Drawer.Screen name="NerdList" component={NerdListStack} />
</Drawer.Navigator>
);
}
export default function OnboardingStack() {
return (
<Stack.Navigator mode="card" headerMode="none">
<Stack.Screen
name="Onboarding"
component={Pro}
option={{
headerTransparent: true
}}
/>
<Stack.Screen name="App" component={AppStack} />
</Stack.Navigator>
);
}
As #satya164 pointed out in a comment here, the problem was that I was passing a param to a nested navigator incorrectly. I was attempting to pass the param with:
onPress={() => this.props.navigation.navigate('Profile', {test: 'Hello'})}
The correct way to pass a param to a nested navigator is:
onPress={() => this.props.navigation.navigate('Profile', {screen: 'Profile', params: {test: 'name'}})}

Resources