React navigation hide drawer item - reactjs

I am using React navigation 5.
I have a settings icon in the header that routes to the Setting Screen. So i want to hide the routes from the drawer.
Here's my code.
My CustomDrawerContent i have
const newState = { ...state };
newState.routes = newState.routes.filter((item) => item.name !== "Setting");
Its render function has:
<DrawerItemList state={newState} {...props} />
still the drawer item for settings has an empty container there. When i do console.log(newState.routes) it doesn't have setting.
Entire file is below
import React, { useContext } from "react";
import { View, StyleSheet } from "react-native";
import { connect } from "react-redux";
import {
Text,
Avatar,
ThemeContext,
Button,
Divider,
SocialIcon,
Icon,
} from "react-native-elements";
import {
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from "#react-navigation/drawer";
import { signOut } from "../store/actions/authActions";
const CustomDrawerContent = (props) => {
const { theme } = useContext(ThemeContext);
const { state } = props;
const signOut = props.signOut;
const newState = { ...state };
newState.routes = newState.routes.filter((item) => item.name !== "Setting");
return (
<View style={{ flex: 1, backgroundColor: "#f5f5f5" }}>
<DrawerContentScrollView {...props}>
<View style={{ paddingVertical: 10, paddingHorizontal: 45 }}>
{/* View for profile pic area */}
<View
style={{
display: "flex",
flexDirection: "column",
marginTop: 25,
}}
>
<Avatar
size="large"
rounded={true}
icon={{ name: "rocket", color: "orange", type: "font-awesome" }}
overlayContainerStyle={{ backgroundColor: "white" }}
onPress={() => console.log("Works!")}
activeOpacity={0.7}
containerStyle={{ flex: 1 }}
/>
<Text
style={{
fontSize: 18,
fontWeight: "bold",
paddingTop: 10,
color: "#555",
}}
>
Olivia Groza
</Text>
<Text style={theme.Text.captionStyles}>#Govliva</Text>
<Button title="Go Pro" containerStyle={{ marginTop: 10 }}></Button>
</View>
</View>
<Divider
style={{ margin: 10, backgroundColor: "#dddddd", height: 1 }}
></Divider>
{console.log(newState.routes)}
<DrawerItemList state={newState} {...props} />
<DrawerItem
icon={({ color, size }) => (
<Icon name="home" type="material-community" color={color} />
)}
label="Logout"
onPress={signOut}
/>
</DrawerContentScrollView>
<View style={styles.shareContainer}>
<SocialIcon type="twitter" iconSize={18} style={styles.iconContainer} />
<SocialIcon
type="facebook"
iconSize={18}
style={styles.iconContainer}
/>
<SocialIcon
type="instagram"
iconSize={18}
style={styles.iconContainer}
/>
</View>
</View>
// <DrawerContentScrollView {...props}>
// <DrawerItemList {...props} />
// <Text>adfafsd</Text>
// </DrawerContentScrollView>
);
};
const styles = StyleSheet.create({
shareContainer: {
paddingHorizontal: 10,
display: "flex",
flexDirection: "row",
// justifyContent: "center"
},
iconContainer: {
height: 40,
width: 40,
},
});
const mapStateToProps = (state) => {
return {};
};
const mapDispathToProps = (dispatch) => {
return {
signOut: () => dispatch(signOut()),
};
};
export default connect(mapStateToProps, mapDispathToProps)(CustomDrawerContent);

Related

CustomDrawerNavigator: Change Active and Inactive Background Colour

On react-navigation/drawer's DrawerItem, is there a way to add active and inactive background colour? I followed this document to implement this https://reactnavigation.org/docs/drawer-navigator/.
I have added theses code lines to the drawerItems. But it won't work for me.
drawerContentOptions={{
activeTintColor: '#fff', /* font color for active screen label */
activeBackgroundColor: '#68f', /* bg color for active screen */
inactiveTintColor: 'grey', /* Font color for inactive screens' labels */
}}
initialized by the following,
import * as React from 'react';
import {
Button,
View,
Text,
StyleSheet,
TouchableOpacity,
Image,
} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
} from '#react-navigation/drawer';
import Home from '../home/containers';
import NavigationService from '../../navigation/NavigationService';
import * as homeActions from '../../features/home/actions';
import * as loginActions from '../../features/login/actions';
import { Images } from '../../config';
import i18n from 'i18n-js';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => NavigationService.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => NavigationService.goBack()} title="Go back home" />
</View>
);
}
function CustomDrawerContent({ props, navigation }) {
const dispatch = useDispatch();
const outlets = useSelector((state) => state.homeReducer.outlets);
const defaultOutLet = useSelector((state) => state.homeReducer.defaultOutLet);
const drawerItems = outlets.map((outlet) => {
return (
console.log("############## nav drawr ################## " + outlet.name),
<DrawerItem
{...props}
key={outlet.userCompanyId}
label={outlet.name}
onPress={() => {
dispatch(homeActions.changeSelectedOutlet(outlet));
navigation.closeDrawer();
}}
/>
);
});
return (
<View style={styles.flexView}>
<View style={styles.container}>
<Image
style={styles.image}
source={Images.icons.logo}
resizeMode="contain"
/>
{defaultOutLet && <Text style={styles.text}>{defaultOutLet.name}</Text>}
</View>
<View style={styles.separator} />
<View style={styles.flexView}>{drawerItems}</View>
<View style={styles.separator} />
<View style={styles.bottomView}>
<TouchableOpacity
style={styles.logoutContainer}
onPress={() => {
dispatch(homeActions.clearUserCompany());
dispatch(loginActions.completeLogOutClearingUserData());
}}>
<Image
style={styles.logoutIcon}
source={Images.icons.power}
resizeMode="center"
/>
<Text style={styles.logoutText}>{i18n.t('common.logout')}</Text>
</TouchableOpacity>
</View>
</View>
);
}
const Drawer = createDrawerNavigator();
export default function DrawerNavigator() {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName="Home">
<Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>
);
}
const styles = StyleSheet.create({
container: {
flex: 0.3,
width: '100%',
backgroundColor: 'white',
},
flexView: {
flex: 1,
},
text: {
marginVertical: 12,
color: 'black',
textAlign: 'center',
},
logoutContainer: {
flexDirection: 'row',
alignItems: 'center',
width: '100%',
},
logoutText: {
color: 'gray',
},
logoutIcon: {
flex: 0.4,
},
image: {
flex: 1,
marginTop: 20,
alignSelf: 'center',
},
separator: {
width: '100%',
height: 1,
backgroundColor: 'gray',
},
bottomView: {
flex: 0.15,
width: '100%',
justifyContent: 'center',
},
});

How to add Fonts into React Expo Project

I am having issues using downloaded fonts into my Expo project.
I have added all the fonts I wanted into assets/fonts folder but even if there are a lot of examples (documentation: https://docs.expo.io/versions/latest/sdk/font/#usefonts) on how to do it I still not have found the solution.
At this moment I am using two Main scripts (App.js and AppScreen.js)
I am looking to add fonts on all the project.
App.js Script:
import React from 'react'
import {Provider} from 'react-redux'
import {createStore, combineReducers} from 'redux'
import { StyleSheet, Text, View, Button, ActivityIndicator } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
import { createStackNavigator } from '#react-navigation/stack'
import { FontAwesome5 } from '#expo/vector-icons'
// Screens
import HomeScreen from './components/screens/HomeScreen'
import ExchangeScreen from './components/screens/ExchangeScreen'
import MessageScreen from './components/screens/MessageScreen'
import NewAdScreen from './components/screens/NewAdScreen'
import ProfileScreen from './components/screens/ProfileScreen'
import AppScreen from './components/screens/AppScreen'
// Reducers
import userConnected from './components/reducers/userConnected'
import { Extrapolate } from 'react-native-reanimated'
import { useFonts } from 'expo-font';
const store = createStore(combineReducers({ userConnected }));
function App() {
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
// const StackMenu = () => {
// return (
// <NavigationContainer>
// <Stack.Navigator>
// <Stack.Screen name='App' component={AppScreen}/>
// </Stack.Navigator>
// </NavigationContainer>
// )
// }
let TabMenu = () => {
return (
<Tab.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = 'home'
} else if (route.name === 'Exchange') {
iconName = 'exchange-alt'
} else if (route.name === 'Message') {
iconName = 'comment-dots'
} else if (route.name === 'NewAd') {
iconName = 'plus-square';
} else if (route.name === 'Profile') {
iconName = 'user';
}
// You can return any component that you like here!
// return <Ionicons name={iconName} size={size} color={color} />;
return <FontAwesome5 name={iconName} size={size} color={color} />
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Exchange" component={ExchangeScreen} />
<Tab.Screen name="Message" component={MessageScreen} />
<Tab.Screen name="NewAd" component={NewAdScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
)
}
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name='App' component={AppScreen} />
<Stack.Screen name='TabMenu' component={TabMenu} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
export default App;
And this AppScreen.js :
// This component implements the "Accueil" screen
import { StatusBar } from "expo-status-bar";
import React, { Component, useEffect, useState } from 'react'
import { StyleSheet, Text, View, Image, ScrollView } from 'react-native'
import { connect } from 'react-redux'
import AsyncStorage from '#react-native-async-storage/async-storage'
import { Input, Button, Overlay, CheckBox } from 'react-native-elements'
import { black, cranberrie, darkGreen, green, grey } from '../../tools/globalVariables'
import { storeLocalData } from '../../tools/functions'
import { useFonts } from 'expo-font';
import * as Font from 'expo-font';
const myIP = '##########'
function AppScreen(props) {
const [screen, setScreen] = useState(false)
const [modalSignUpVisible, setModalSignUpVisible] = useState(false)
const [modalSignInVisible, setModalSignInVisible] = useState(false)
const [firstName, setFirstName] = useState('')
const [lastName, setLastName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
// States for Sign In
const [wrongPassSignIn, setWrongPassSignIn] = useState(false)
const [wrongEmailSignIn, setWrongEmailSignIn] = useState(false)
const [labelPassSignIn, setLabelPassSignIn] = useState('Mot de passe')
const [labelMailSignIn, setLabelMailSignIn] = useState('Email')
// States for Sign Up
const [wrongFirstName, setWrongFirstName] = useState(false)
const [wrongLastName, setWrongLastName] = useState(false)
const [wrongEmail, setWrongEmail] = useState(false)
const [wrongPassword, setWrongPassword] = useState(false)
const [labelFirstName, setLabelFirstName] = useState('Prénom')
const [labelLastName, setLabelLastName] = useState('Nom')
const [labelEmail, setLabelEmail] = useState('Email')
const [labelPassword, setLabelPassword] = useState('Mot de passe')
const [proAccount, setProAccount] = useState(false)
useEffect(() => {
// Show logo at first for 2 seconde, then the application screen
const timer = setTimeout(() => {
setScreen(true)
}, 2000);
const getData = async () => {
try {
const value = await AsyncStorage.getItem('userToken')
if (value !== null) {
const rawAnswer = await fetch(`http://${myIP}:3000/user/userInfos?token=${value}`)
const answer = await rawAnswer.json()
props.saveUser(answer.user)
props.navigation.navigate('TabMenu', { screen: 'Home' })
}
} catch (e) {
console.log('ERROR : ', e)
}
}
getData()
return () => clearTimeout(timer);
}, []);
/////// SIGN UP
const handleSignUp = async () => {
const dataUser = {
firstname: firstName,
lastname: lastName,
email,
password,
proAccount
}
///// Sending request to server //////
const rawAnswer = await fetch('http://' + myIP + ':3000/user/sign-up', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(dataUser)
});
const answer = await rawAnswer.json();
if (answer.result) {
// TO DO : STORE IN LOCAL STORAGE //
// Reset states values
setFirstName('')
setLastName('')
setEmail('')
setPassword('')
setProAccount(false)
setModalSignUpVisible(false)
props.navigation.navigate('TabMenu', { screen: 'Home' })
} else {
// Errors gestion
answer.error.map((err) => {
if (err.includes("firstname")) {
setWrongFirstName(true)
setLabelFirstName('Le prénom doit avoir 2 caractères minimum')
}
if (err.includes("lastname")) {
setWrongLastName(true)
setLabelLastName('Le nom doit avoir 2 caractères minimum')
}
if (err.includes("password")) {
setWrongPassword(true)
setLabelPassword('Le mot de passe doit faire entre 6 et 50 caractères')
}
if (err.includes("email")) {
setWrongEmail(true)
if (err.includes("existant")) {
setLabelEmail('Email déjà existant')
} else {
setLabelEmail("L'email doit être au bon format")
}
}
})
}
}
/////// SIGN IN
const handleSignIn = async () => {
console.log('Sign in')
const connexionData = {
email,
password
}
///// Sending request to server //////
const rawAnswer = await fetch('http://' + myIP + ':3000/user/sign-in', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(connexionData)
});
const answer = await rawAnswer.json();
console.log(answer.error)
if (answer.result) {
setEmail('')
setPassword('')
// Save in Local Storage
props.saveUser(answer.userFound)
await AsyncStorage.setItem('userToken', answer.userFound.token)
setModalSignInVisible(false)
props.navigation.navigate('TabMenu', { screen: 'Home' })
} else {
if (answer.error.indexOf('inexisting email') >= 0) {
setEmail('')
setPassword('')
setWrongEmailSignIn(true)
setLabelMailSignIn('Email inconnu')
setWrongPassSignIn(false)
setLabelPassSignIn('Mot de passe')
} else {
setPassword('')
setWrongPassSignIn(true)
setLabelPassSignIn('Mot de passe incorrect')
setWrongEmailSignIn(false)
setLabelMailSignIn('Email')
}
}
}
const handleCancel = () => {
// Reset state values and labels
setFirstName('')
setLastName('')
setEmail('')
setPassword('')
setProAccount(false)
setModalSignUpVisible(false)
setModalSignInVisible(false)
setWrongEmailSignIn(false)
setWrongPassSignIn(false)
setWrongPassword(false)
setWrongEmail(false)
setWrongFirstName(false)
setWrongLastName(false)
setLabelPassSignIn('Mot de passe')
setLabelMailSignIn('Email')
setLabelEmail('Email')
setLabelPassword('Mot de passe')
setLabelFirstName('Prénom')
setLabelLastName('Nom')
}
return (
<View>
{
screen ?
<View style={{ flexDirection: 'column', alignItems: 'center', backgroundColor: 'white', height: '100%', width: '100%' }}>
<Image source={require('../../assets/logoSmallBlack.png')} style={{ width: '30%', height: '25%', resizeMode: 'contain' }} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between', height: '50%', width: '100%' }}>
<Image source={require('../../assets/planteGauche.png')} style={{ width: '32%', height: '72%', resizeMode: 'contain' }} />
<Image source={require('../../assets/planteCentre.png')} style={{ width: '32%', height: '72%', resizeMode: 'contain', marginTop: 45 }} />
<Image source={require('../../assets/planteDroite.png')} style={{ width: '30%', height: '72%', resizeMode: 'contain' }} />
</View>
<StatusBar style="auto" />
<View >
<Text style={{ color: black, fontSize: 20, paddingBottom:-20 }}>Les plus belles plantes</Text>
<Text style={{ color: black, fontSize: 20, fontFamily: 'Recoleta'}}>près de chez toi !</Text>
</View>
{/* SIGN UP OVERLAY */}
<Overlay isVisible={modalSignUpVisible} onBackdropPress={() => { setModalSignUpVisible(!modalSignUpVisible); }}>
<View style={{ width: '80%' }}>
<ScrollView>
<Text style={{ textAlign: "center" }}>S'inscrire</Text>
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelFirstName} labelStyle={[wrongFirstName ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre prénom' value={firstName} onChangeText={(value) => setFirstName(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelLastName} labelStyle={[wrongLastName ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre nom' value={lastName} onChangeText={(value) => setLastName(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelEmail} labelStyle={[wrongEmail ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre email' value={email} onChangeText={(value) => setEmail(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelPassword} labelStyle={[wrongPassword ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} secureTextEntry={true} placeholder='Entrez votre mot de passe' value={password} onChangeText={(value) => setPassword(value)} />
<CheckBox title='Je suis un professionnel' textStyle={{ fontSize: 12 }} containerStyle={{ backgroundColor: "transparent", borderWidth: 0, marginTop: -20, marginLeft: 0 }} checked={proAccount} onPress={() => { setProAccount(!proAccount) }} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between', width: '100%' }}>
<Button title='Annuler' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleCancel() }} />
<Button title='Valider mon inscription' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleSignUp() }} />
</View>
</ScrollView>
</View>
</Overlay>
{/* SIGN IN OVERLAY */}
<Overlay isVisible={modalSignInVisible} onBackdropPress={() => { setModalSignInVisible(!modalSignInVisible); }}>
<View style={{ width: '80%' }}>
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelMailSignIn} labelStyle={[{ fontSize: 15 }, wrongEmailSignIn ? { color: cranberrie } : { color: black }]} placeholder='Entrez votre email' value={email} onChangeText={(value) => setEmail(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelPassSignIn} labelStyle={[{ fontSize: 15 }, wrongPassSignIn ? { color: cranberrie } : { color: black }]} secureTextEntry={true} placeholder='Entrez votre mot de passe' value={password} onChangeText={(value) => setPassword(value)} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Button title='Annuler' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleCancel() }} />
<Button title='Me connecter' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleSignIn() }} />
</View>
</View>
</Overlay>
<Button title="S'inscrire sur Plan.T" buttonStyle={{ backgroundColor: black, borderRadius: 5, width: '100%' }} onPress={() => { setModalSignUpVisible(true) }} />
<Button title="J'ai déjà un compte" buttonStyle={{ backgroundColor: 'white', borderRadius: 5, width: '100%', borderColor: '1px solid black' }} titleStyle={{ color: black }} onPress={() => { setModalSignInVisible(true) }} />
</View>
:
<View style={{ backgroundColor: darkGreen, height: '100%', justifyContent: 'center', alignItems: 'center' }}>
<Image source={require('../../assets/logo.png')} style={{ width: '70%', resizeMode: 'contain' }} />
</View>
}
</View>
)}
function mapDispatchToProps(dispatch) {
return {
saveUser: function (user) {
dispatch({ type: 'saveUser', user })
}
}
}
export default connect(
null,
mapDispatchToProps
)(AppScreen)
In my case I've added 26 fonts (see picture) :
Here the fonts I've added into asset/fonts folder
Let's say that I would like to use Recoleta Bold.otf inside a text part in AppScreen.js
How would you do this?
Thanks in advance for your time and help ! Much appreciate it.
I am adding a code snippet as an example from the official expo docs for easy reference.
import React from 'react';
import { Text, View } from 'react-native';
import AppLoading from 'expo-app-loading';
import { useFonts } from 'expo-font';
export default props => {
let [fontsLoaded] = useFonts({
'Inter-Black': require('./assets/fonts/Inter-Black.otf'),
});
if (!fontsLoaded) {
return <AppLoading />;
} else {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontFamily: 'Inter-Black', fontSize: 40 }}>Inter Black</Text>
<Text style={{ fontSize: 40 }}>Platform Default</Text>
</View>
);
}
};
Incase you want to dive more deep here is the link to official expo docs

How to set the dropdown state to initial whenever I switch Tabs?

I have a bottomtabbar with three screens, all the screens are have a dropdown picker at the header.
Whenever I have my dropdown open and I change the tab screen, my dropdown is still remains opened, however I would like my dropdown to remain closed initially whenever I changed tabs.
My exact code is as follows:
import React, {useEffect, useState} from 'react';
import {ActivityIndicator} from 'react-native';
import {SafeAreaView, View, Image, TouchableOpacity} from 'react-native';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
// bottom tab
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/FontAwesome';
import DropDownPicker from 'react-native-dropdown-picker';
//tabs component
import HomeTabScreen from './HomeTabScreen';
import ConsultationHomeScreen from '../Consult/ConsultationHomeScreen';
import PlansTabScreen from './PlansTabScreen';
import ChatTabScreen from './ChatTabScreen';
import {useSelector, useDispatch} from 'react-redux';
import {
setSelectedChild,
setSelectedChildId,
} from '../../store/actions/userActions';
import {isValidObject} from '../../utils/baseUtils';
import {getChildFromUserChildrenList} from '../../utils/userUtils';
import {setAppReload} from '../../store/actions/HomeActions';
export default function PLHomeScreen(props) {
const {navigation} = props;
const [loading, setLoading] = useState(false);
const Tab = createBottomTabNavigator();
//child related
const [loadApi, setLoadApi] = useState(true);
//Use for all the dispatch actions
const dispatch = useDispatch();
const User = useSelector((state) => state.userReducer.user);
const mSChildId = useSelector((state) => state.userReducer.selectedChildId);
let mChild = getChildFromUserChildrenList(User, mSChildId);
const defaultchildvalue = getChildFromUserChildrenList(User, mSChildId);
const reloadApp = useSelector(
(state) => state.premiumCardActionTypesReducer.reloadApp,
);
console.log('!!!! Reload App !!!!', reloadApp);
useEffect(() => {
if (!isValidObject(mChild)) {
if (!isValidObject(mSChildId)) {
let cid = User.children[0].id;
handleChangeChild(cid);
}
}
if (loadApi == true) {
setLoadApi(false);
setLoading(false);
}
if (reloadApp == true) {
setLoadApi(true);
setLoading(true);
dispatch(setAppReload(false));
}
console.log('!!!! Reload App !!!!', reloadApp);
}, [User, mSChildId, loadApi, reloadApp]);
const handleChangeChild = (id) => {
dispatch(setSelectedChildId(id));
mChild = getChildFromUserChildrenList(User, id);
setLoadApi(true);
setLoading(true);
};
return (
<SafeAreaView
style={{
flex: 1,
alignItems: 'stretch',
justifyContent: 'center',
backgroundColor: '#FE017E',
}}>
<View>
<View
style={{
height: 56,
backgroundColor: '#FE017E',
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<TouchableOpacity
onPress={() => navigation.openDrawer()}
style={{
backgroundColor: '#FE017E',
width: '100%',
height: 40,
padding: 10,
}}
underlayColor="transparent">
<Icon size={20} name="bars" style={{marginLeft: 2}} color="#fff" />
</TouchableOpacity>
</View>
{User != null &&
User.children != undefined &&
User.children != null &&
User.children.length > 0 &&
mChild &&
mChild != undefined &&
mChild != null && (
<DropDownPicker
items={User.children.map((item) => {
return {
label: item.name + '\n' + item.dob_text,
value: item,
icon: () =>
item.pic_url ? (
<Image
source={{
uri: item.pic_url,
}}
style={{height: 30, width: 30, borderRadius: 15}}
/>
) : item.gender === 'male' ? (
<Image
source={{
uri:
'https://cdn3.iconfinder.com/data/icons/materia-human/24/013_042_newborn_infant_child_baby-512.png',
}}
style={{height: 30, width: 30}}
/>
) : (
<Image
source={{
uri:
'https://cdn3.iconfinder.com/data/icons/materia-human/24/013_042_newborn_infant_child_baby-512.png',
}}
style={{height: 30, width: 30}}
/>
),
};
})}
onChangeItem={(item) => {
if (item.value.id != mSChildId) {
handleChangeChild(item.value.id);
}
}}
containerStyle={{
marginLeft: 60,
marginTop: -46,
marginBottom: 10,
height: 40,
}}
defaultValue={defaultchildvalue}
dropDownStyle={{
backgroundColor: '#ffffff',
marginLeft: 40,
borderColor: 'grey',
borderWidth: 1,
borderBottomEndRadius: 0,
borderBottomLeftRadius: 0,
borderBottomStartRadius: 0,
borderBottomRightRadius: 0,
minWidth: 100,
maxWidth: 150,
}}
itemStyle={{
justifyContent: 'flex-start',
fontWeight: 'bold',
fontSize: 20,
borderColor: '#FE017E',
}}
style={{
backgroundColor: '#FE017E',
borderBottomEndRadius: 0,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
borderBottomStartRadius: 0,
borderTopEndRadius: 0,
borderTopLeftRadius: 0,
borderRadius: 0,
borderColor: '#FE017E',
minWidth: 100,
maxWidth: 150,
}}
labelStyle={{
marginLeft: 15,
fontWeight: 'bold',
fontSize: 10,
color: 'black',
textAlign: 'center',
}}
arrowColor={'white'}
activeLabelStyle={{color: '#FE017E'}}
selectedLabelStyle={{color: 'white'}}
/>
)}
</View>
{loading ? (
<ActivityIndicator
color="#FF1493"
size="large"
style={{
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
flexDirection: 'row',
}}
/>
) : (
// <View>
<Tab.Navigator
lazy={true}
initialRouteName="Home"
tabBarOptions={{
labelStyle: {
color: '#FF1493',
fontSize: 12,
},
}}>
<Tab.Screen
name="Home"
// uncommnet below line to see new Home Tab
component={HomeTabScreen}
// uncomment below see old Home Tab
// component={HomeScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({}) => (
<MaterialIcon name="home" color="#FF1493" size={30} />
),
}}
/>
<Tab.Screen
name="Consult"
component={ConsultationHomeScreen}
initialParams={{
mSChildId: mSChildId,
}}
options={{
tabBarLabel: 'Consult',
tabBarIcon: ({}) => (
<FontAwesomeIcon name="stethoscope" color="#FF1493" size={30} />
),
}}
/>
{mChild != null && mChild.is_sc_subscribed == true ? (
<Tab.Screen
name="Chat"
component={ChatTabScreen}
options={{
tabBarLabel: 'Chat',
tabBarIcon: ({}) => (
<MaterialCommunityIcons
name="chat-outline"
color="#FF1493"
size={30}
/>
),
}}
/>
) : (
<Tab.Screen
name="Plans"
component={PlansTabScreen}
options={{
tabBarLabel: 'Plans',
tabBarIcon: ({}) => (
<MaterialCommunityIcons
name="crown-outline"
color="#FF1493"
size={30}
/>
),
}}
/>
)}
</Tab.Navigator>
)}
</SafeAreaView>
);
}
Kindly, let me know how do I let my dropdown remain closed whenever I switch tabs.
Any lead would be appreciated.
Define a controller for your dropdown picker then add a custom buttons to your tab navigator. The custom buttons would allow you implement an onPress listener and in the listener you can run controller.close() to close the dropdown picker.
You can check the npm page if you're not familiar with controllers for the dropdown picker
Edit: Here's how to set a controller as per the npm page:
const [value, setValue] = useState(null);
const [items, setItems] = useState([ {...}, ... ]);
let controller;
<DropDownPicker
items={items}
controller={instance => controller = instance}
onChangeList={(items, callback) => {
new Promise((resolve, reject) => resolve(setItems(items)))
.then(() => callback())
.catch(() => {});
}}
defaultValue={value}
onChangeItem={item => setValue(item.value)}
/>
then you can use the controller wherever you want in your code.

console.error:"the action navigate with payload...was not handled..."

I'm having an issue with the "onLogin" function within the "LoginComponent". After pressing the TouchableOpacity that handles that function, I want the user to then be directed to the "HomeComponent", but instead I get this console.error: "the action navigate with payload...was not handled..." Anybody know why this is? Any help would be greatly appreciated. Thanks!
import React, { Component } from 'react';
import 'react-native-gesture-handler';
import { createStackNavigator } from '#react-navigation/stack';
import WelcomeScreen from './WelcomeComponent';
import LoginScreen from './LoginComponent';
import RegisterScreen from './RegisterComponent';
import HomeScreen from './HomeComponent';
import { NavigationContainer } from '#react-navigation/native';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import { AsyncStorage } from 'react-native';
const AuthStack = createStackNavigator();
const AuthStackScreen = () => {
return <AuthStack.Navigator initialRouteName="Welcome">
<AuthStack.Screen name="Welcome" component={WelcomeScreen} />
<AuthStack.Screen name="Login" component={LoginScreen} />
<AuthStack.Screen name="Register" component={RegisterScreen} />
</AuthStack.Navigator>
};
const HomeTab = createMaterialBottomTabNavigator();
const HomeTabScreen = () => {
return <HomeTab.Navigator initialRouteName="Home">
<HomeTab.Screen name="Home" component={HomeScreen} />
</HomeTab.Navigator>
}
class Navigation extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
};
this.loginStatusCheck();
}
loginStatusCheck = async () => {
const userToken = await AsyncStorage.getItem("userprofile");
if(userToken) {
this.setState({ isLoggedIn: true })
} else {
this.setState({ isLoggedIn: false })
}
}
render() {
return(
<NavigationContainer>
{this.state.isLoggedIn ? <AuthStackScreen /> : <HomeTabScreen />}
</NavigationContainer>
);
};
};
export default Navigation;
import React, { Component } from 'react';
import { StyleSheet, SafeAreaView, ScrollView, View, TouchableOpacity, Text, Linking, AsyncStorage } from 'react-native';
import { Input, CheckBox } from 'react-native-elements';
import { FontAwesome } from '#expo/vector-icons';
class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password:"",
token: "",
remember: false
};
this.getData();
};
handleUsernameChange = username => {
this.setState({ username })
};
handlePasswordChange = password => {
this.setState({ password })
};
onLogin = async () => {
try {
await AsyncStorage.setItem("userprofile", JSON.stringify({ username: this.state.username, password: this.state.password }));
this.props.navigation.navigate("Home", {
screen: "HomeScreen",
});
} catch (err) {
console.log(err);
}
};
getData = async () => {
try {
const userprofile = await AsyncStorage.getItem("userprofile");
const userProfile = JSON.parse(userprofile);
if (userProfile !== null) {
this.setState({ ...userProfile })
}
if (username !== null) {
this.setState({ username })
}
if (password !== null) {
this.setState({ password })
}
} catch (err) {
console.log(err);
}
}
render() {
const { username, password } = this.state;
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<Text style={styles.titleText}>Login</Text>
<Text style={styles.fillerText}>Hi there! Nice to see you again.</Text>
<Input
inputStyle={{color: 'white'}}
placeholder="Enter username"
onChangeText={this.handleUsernameChange}
value={username}
keyboardType="email-address"
autoCapitalize="none"
leftIcon={{ type: 'font-awesome', name: 'user-circle-o', color: 'white', marginRight: 10 }}
/>
<Input
inputStyle={{color: 'white'}}
placeholder="Password"
secureTextEntry
onChangeText={this.handlePasswordChange}
value={password}
leftIcon={{ type: 'font-awesome', name: 'lock', color: 'white', marginRight: 10 }}
/>
<CheckBox
title="Remember Me"
checked={this.state.remember}
onPress={() => this.setState({remember: !this.state.remember})}
containerStyle={styles.rememberCheckbox}
textStyle={{color: 'white'}}
checkedColor="crimson"
/>
<TouchableOpacity
style={styles.loginButton}
title="Login" type="submit"
onPress={this.onLogin}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<Text style={{textAlign: 'center', color: 'grey', marginTop: 20}}>
OR use an account from one of the following:
</Text>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.twitterButton}>
<FontAwesome name="twitter" color="white" style={{marginRight: 5}}/>
<Text style={{color: 'white'}}>Twitter</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.facebookButton}>
<FontAwesome name="facebook-square" color="white" style={{marginRight: 5}}/>
<Text style={{color: 'white'}}>Facebook</Text>
</TouchableOpacity>
</View>
<View style={{alignItems: 'center'}}>
<TouchableOpacity style={styles.googleButton}>
<FontAwesome name="google" color="black" style={{marginRight: 5}}/>
<Text style={{color: 'grey'}}>Google</Text>
</TouchableOpacity>
</View>
<View style={styles.linkContainer}>
<TouchableOpacity style={{marginTop: 75}} onPress={() => Linking.openURL('#')}>
<Text style={{color: 'white'}}>
Forgot Your Password?
</Text>
</TouchableOpacity>
<TouchableOpacity style={{marginTop: 75, marginLeft: 210}} onPress={() => Linking.openURL('#')}>
<Text style={{color: 'white'}}>
Register
</Text>
</TouchableOpacity>
</View>
</ScrollView>
</SafeAreaView>
);
};
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'black'
},
buttonsContainer: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row'
},
linkContainer: {
flex: 3,
justifyContent: 'center',
flexDirection: 'row'
},
titleText: {
fontSize: 26,
color: 'white',
marginBottom: 30,
marginTop: 20
},
fillerText: {
color: 'grey',
marginBottom: 20
},
loginButton: {
backgroundColor: 'crimson',
paddingVertical: 17,
paddingHorizontal: 25,
borderRadius: 20,
textAlign: 'center'
},
buttonText: {
color: 'white',
fontSize: 18,
textAlign: 'center'
},
twitterButton: {
backgroundColor: '#00acee',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
facebookButton: {
backgroundColor: '#4267B2',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
googleButton: {
backgroundColor: '#FFFFFF',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
rememberCheckbox: {
margin: 10,
marginBottom: 20,
backgroundColor: null
}
});
export default LoginScreen;
I don't think its necessary to use navigate in your LoginScreen component, since you've already written code that conditionally renders two navigators based on the value of isLoggedIn.
What you're missing in your current implementation is a way to update isLoggedIn from within your LoginScreen component. Then if isLoggedIn is updated and set to true, the Navigation component will be re-rendered and the HomeScreen component is shown without having to navigate.
I've chosen to use react context here, but you could also use this approach with something like redux also if you prefer that. The reason to use something like react context is to be able to easily pass isLoggedIn and its setter between components.
I'll give a more general example, because its easier to illustrate the approach that way:
// Imports and other stuff...
const LoginContext = React.createContext([null, () => {}]);
const LoginContextProvider = props => {
const [isLoggedIn, setIsLoggedIn] = React.useState(false);
return (
<LoginContext.Provider value={[isLoggedIn, setIsLoggedIn]}>
{props.children}
</LoginContext.Provider>
);
};
const HomeScreen = () => {
return (
<View>
<Text>HomeScreen</Text>
</View>
);
};
const LoginScreen = () => {
const [isLoggedIn, setIsLoggedIn] = React.useContext(LoginContext);
return (
<View>
<Text>LoginScreen</Text>
<Button
title="login"
onPress={() => {
setIsLoggedIn(true);
}}
/>
</View>
);
};
const HomeTabScreen = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
</Tab.Navigator>
);
};
const AuthStackScreen = ({ navigation }) => {
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
</Stack.Navigator>
);
};
const Navigation = () => {
const [isLoggedIn, setIsLoggedIn] = React.useContext(LoginContext);
return (
<NavigationContainer>
{isLoggedIn ? <HomeTabScreen /> : <AuthStackScreen />}
</NavigationContainer>
);
};
export default function App() {
return (
<LoginContextProvider>
<Navigation />
</LoginContextProvider>
);
}
So the approach shown above is to create a provider that holds your isLoggedIn state and setter (setIsLoggedIn). Then when we wrap Navigation with this provider so we can access isLogged and setIsLoggedIn from any component inside the provider, allowing us to update the isLogged state inside the LoginScreen component. When this state updates, the provider and everything inside it (i.e. Navigation), will re-render and show the HomeScreen component.
Normally the convention is to put most the react context related stuff in its own file and import parts in components where you need them, but for demonstration purposes I haven't done this.

how to make initialParams updated

I want to update initialParams of react native navigation on clicking of the menu item
import React, { useState } from 'react';
import {createStackNavigator} from '#react-navigation/stack'
import { NavigationContainer } from '#react-navigation/native';
import userMain from './../../components/users/userMain';
import { View, Icon } from 'native-base';
export const UserStack = () => {
const Stack = new createStackNavigator()
const [toggleSearch, setToggleSearch] = useState(true)
const changeStyleToggle = () => {
setToggleSearch( !toggleSearch )
// console.log('toggle search here ==== ', toggleSearch)
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="User Homepage"
component={userMain}
initialParams={{ toggleSearch: toggleSearch}}
options = {{
title: 'My home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
headerRight: () => (
<View style={{flexDirection:'row', justifyContent:'space-evenly', width:120}}>
<Icon name='home' onPress={() => changeStyleToggle()} />
<Icon name='home' />
<Icon name='home' />
</View>
),
}}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
the component i am calling is userMain where i am calling initialParams value and on behalf of that i want to change style
import React from 'react'
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'
import { Input } from 'native-base';
const userMain = (props) => {
const {toggleSearch} = props.route.params;
console.log(toggleSearch)
const check = toggleSearch == true ? 'true!!' : 'false!!'
return (
<View style={styles.container}>
<Input
placeholder="search"
style={styles.searchInput}
/>
<Text>user homepage here</Text>
<Text>{check}</Text>
<TouchableOpacity style={styles.btn}>
<Text style={styles.btnText}> + </Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
container: {
alignItems: 'center', flex: 1, justifyContent: 'center',
},
btn: {
position: 'absolute', justifyContent: 'center', alignItems: 'center',
bottom:10, right:10, width:60, height: 60,
backgroundColor: '#fff', borderRadius: 50, borderColor: '#000',borderWidth:1,
},
btnText: {
fontSize: 50, color: 'black',
},
searchInput: {
position:'absolute', top: 0, borderWidth: 1, width: 300, opacity:0
}
})
export default userMain
i have checked on clicking the icon state which is toggleSearch is updating but it is not updating the initialParams hence it is not working on userMain component as well .

Resources