Why useState is not working in React Native? [duplicate] - reactjs

This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 10 months ago.
I am getting an error that I do not understand in the application I developed in React Native Expo. The error is as follows; In asyncstorage I keep the name of the user logged into the application. But when I try to set it while the page is loading (useEffect), setLastUser doesn't work. When I do CTRL+S on the keyboard while trying on the same page, I get the following output.
Prev CTRL+S
After CTRL+S
Can you help me? Thanks.
App.js Code
import { StatusBar } from 'expo-status-bar';
import React, { useState, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import SignIn from './SignIn';
import SignUp from './SignUp';
import Conversation from './Conversation';
import Contacts from './Contacts';
import Settings from './Settings';
import Chats from './Chats';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {Ionicons} from '#expo/vector-icons'
import { UserProvider } from './UserContext';
import { LogBox } from "react-native"
const Stack = createNativeStackNavigator();
const Tabs = createBottomTabNavigator();
const TabsNavigator = () => (
<Tabs.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
return <Ionicons name={route.name === "Chats" ? "chatbubble-ellipses-outline" : route.name === "Contacts" ? "people-outline" : "settings-outline"} color={color} size={size} />
}})}>
<Tabs.Screen name="Chats" component={Chats} />
<Tabs.Screen name="Contacts" component={Contacts} />
<Tabs.Screen name="Settings" component={Settings} />
</Tabs.Navigator>
);
export default function App() {
LogBox.ignoreAllLogs(true);
// const [lastUser, setLastUser] = useState('none');
// const value = useMemo(
// () => ({ lastUser, setLastUser }),
// [lastUser]
// );
return (
<UserProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{headerShown : false }} name="SignIn" component={SignIn} />
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ headerTitle:'Login', headerBackVisible : true, headerBackTitleVisible :true}}
/>
<Stack.Screen name="Home" component={TabsNavigator} options={{headerShown : false, headerBackTitleVisible : false}}/>
<Stack.Screen name="Contacts" component={Contacts} options={{ headerTitle:'ChatApp'}}/>
<Stack.Screen name="Conversation" component={Conversation} options={{ headerTitle:'ChatApp'}}/>
</Stack.Navigator>
</NavigationContainer>
</UserProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
SignIn.js code
import { useNavigation } from '#react-navigation/core'
import React, { useEffect, useState, createContext, useContext } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View, Image } from 'react-native'
import { borderColor } from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes'
import { auth, firebase } from './firebase'
import { userContext } from './UserContext'
import AsyncStorage from '#react-native-async-storage/async-storage';
const SignIn = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const navigation = useNavigation()
const value = useContext(userContext);
const handleLogin = async() => {
await auth
.signInWithEmailAndPassword(email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with:', user.email);
getUser(user.email);
navigation.replace("Home");
})
.catch(error => alert(error.message))
}
const getUser = async (email2) => {
await firebase.database().ref().child('users').orderByChild('email').equalTo(email2).once('value').then((data) => {
data.forEach((node) => {
storeUser(node.val().username); // one data
}
)
}
)
}
const storeUser = async(data) => {
try{
await AsyncStorage.setItem('sertacKul', data);
}catch(err){
console.log(err);
}
}
return(
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<Image style={styles.logo} source={require('./img/logo.png')}>
</Image>
<TextInput
placeholder="Email"
value={email}
onChangeText={text => setEmail(text)}
style={styles.input}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={text => setPassword(text)}
style={styles.input}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={handleLogin}
style={styles.button}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => navigation.navigate('SignUp')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => value.setData('ebebbebebe')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>{value.lastUser}</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default SignIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor : 'white'
},
logo :{
resizeMode :'contain',
width: '100%',
marginBottom : 40
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: '#eeeeee',
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#06d6cc',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: 'white',
marginTop: 5,
borderColor: '#06d6cc',
borderWidth: 2,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#06d6cc',
fontWeight: '700',
fontSize: 16,
},
})
Contact.js code
import React, { useState, useEffect, useContext } from "react";
import {
StyleSheet,
View,
TextInput,Text
} from "react-native";
import { auth, firebase } from "./firebase";
import { List, Avatar, Divider, FAB } from "react-native-paper";
import uuid from "react-native-uuid";
import moment from "moment";
import { userContext } from "./UserContext";
import AsyncStorage from '#react-native-async-storage/async-storage';
const Contacts = () => {
const [username, setUsername] = useState("");
const value = useContext(userContext);
const [contactList, setContactList] = useState([{}]);
const [lastUser, setLastUser] = useState('');
useEffect(() => {
setContactList([])
setLastUser(() => getUserName()) // ıs not work
console.log('deneme',lastUser)
getContacts();
}, [])
async function getUserName(){
let user = await AsyncStorage.getItem('sertacKul');
return user;
}
const addFriend = () => {
console.log(value.lastUser)
firebase
.database()
.ref("/users/")
.once("value")
.then((data) => {
let id = uuid.v4();
firebase
.database()
.ref("/friendrelations/" + id)
.set({
id: id,
user1: username,
user2: lastUser,
relationtype: "normal",
createdDate: moment().format("DD/MM/YYYY HH:mm:ss"),
})
.then(() => alert("Friend added."));
});
};
const getContacts = async() => {await firebase.database().ref().child('friendrelations').orderByChild('user2').equalTo(() => getUserName())
.once('value').then(data => {
data.forEach((node) => { setContactList(lastContacts => [...lastContacts, node.val().user1])})
})}
return (
<View>
<TextInput
placeholder="Yeni Arkadaş"
value={username}
style={styles.input}
onChangeText={(text) => setUsername(text)}
/>
<FAB
onPress={() => addFriend()}
icon="plus"
style={{ position: "absolute", right: 16 }}
/>
{/*
BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI
{contactList && contactList.map((item)=>{
return( <List.Item onPress={() => navigation.navigate('Conversation')} title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
)
})} */}
<Divider inset/>
</View>
);
};
export default Contacts;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
},
logo: {
resizeMode: "contain",
width: "100%",
marginBottom: 40,
},
inputContainer: {
width: "80%",
},
input: {
backgroundColor: "#eeeeee",
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: "60%",
justifyContent: "center",
alignItems: "center",
marginTop: 40,
},
button: {
backgroundColor: "#06d6cc",
width: "100%",
padding: 15,
borderRadius: 10,
alignItems: "center",
},
buttonOutline: {
backgroundColor: "white",
marginTop: 5,
borderColor: "#06d6cc",
borderWidth: 2,
},
buttonText: {
color: "white",
fontWeight: "700",
fontSize: 16,
},
buttonOutlineText: {
color: "#06d6cc",
fontWeight: "700",
fontSize: 16,
},
});

You have to await the response of getUserName function. A good option is place the content of useEffect inside a async function. For example:
useEffect(() => {
setContactList([]);
updateLastUserName();
getContacts();
}, []);
useEffect(() => {
// Need to wait the lastUser state change to can use it
console.log(lastUser);
}, [lastUser]);
async function updateLastUserName(){
const username = await getUserName();
setLastUser(username);
}
async function getUserName(){
const user = await AsyncStorage.getItem('sertacKul');
return user;
}

Related

Data exists, but the map function returns no value React Native

I guess I'm not realizing something. I have the structure where I list the friends of the logged in user. Data appears to exist on console.log, but the map function does not work. Also, when I press the component in tab transitions, useEffect only works once. It doesn't work after that. Can you help me? Thanks.
App.js code
import { StatusBar } from 'expo-status-bar';
import React, { useState, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import SignIn from './SignIn';
import SignUp from './SignUp';
import Conversation from './Conversation';
import Contacts from './Contacts';
import Settings from './Settings';
import Chats from './Chats';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {Ionicons} from '#expo/vector-icons'
import { UserProvider } from './UserContext';
import { LogBox } from "react-native"
const Stack = createNativeStackNavigator();
const Tabs = createBottomTabNavigator();
const TabsNavigator = () => (
<Tabs.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
return <Ionicons name={route.name === "Chats" ? "chatbubble-ellipses-outline" : route.name === "Contacts" ? "people-outline" : "settings-outline"} color={color} size={size} />
}})}>
<Tabs.Screen name="Chats" component={Chats} />
<Tabs.Screen name="Contacts" component={Contacts} />
<Tabs.Screen name="Settings" component={Settings} />
</Tabs.Navigator>
);
export default function App() {
LogBox.ignoreAllLogs(true);
// const [lastUser, setLastUser] = useState('none');
// const value = useMemo(
// () => ({ lastUser, setLastUser }),
// [lastUser]
// );
return (
<UserProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{headerShown : false }} name="SignIn" component={SignIn} />
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ headerTitle:'Login', headerBackVisible : true, headerBackTitleVisible :true}}
/>
<Stack.Screen name="Home" component={TabsNavigator} options={{headerShown : false, headerBackTitleVisible : false}}/>
<Stack.Screen name="Contacts" component={Contacts} options={{ headerTitle:'ChatApp'}}/>
<Stack.Screen name="Conversation" component={Conversation} options={{ headerTitle:'ChatApp'}}/>
</Stack.Navigator>
</NavigationContainer>
</UserProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
SignIn.js code
import { useNavigation } from '#react-navigation/core'
import React, { useEffect, useState, createContext, useContext } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View, Image } from 'react-native'
import { borderColor } from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes'
import { auth, firebase } from './firebase'
import { userContext } from './UserContext'
import AsyncStorage from '#react-native-async-storage/async-storage';
const SignIn = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const navigation = useNavigation()
const value = useContext(userContext);
const handleLogin = async() => {
await auth
.signInWithEmailAndPassword(email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with:', user.email);
getUser(user.email);
navigation.replace("Home");
})
.catch(error => alert(error.message))
}
const getUser = async (email2) => {
await firebase.database().ref().child('users').orderByChild('email').equalTo(email2).once('value').then((data) => {
data.forEach((node) => {
storeUser(node.val().username); // one data
}
)
}
)
}
const storeUser = async(data) => {
try{
await AsyncStorage.setItem('sertacKul', data);
}catch(err){
console.log(err);
}
}
return(
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<Image style={styles.logo} source={require('./img/logo.png')}>
</Image>
<TextInput
placeholder="Email"
value={email}
onChangeText={text => setEmail(text)}
style={styles.input}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={text => setPassword(text)}
style={styles.input}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={handleLogin}
style={styles.button}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => navigation.navigate('SignUp')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => value.setData('ebebbebebe')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>{value.lastUser}</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default SignIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor : 'white'
},
logo :{
resizeMode :'contain',
width: '100%',
marginBottom : 40
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: '#eeeeee',
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#06d6cc',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: 'white',
marginTop: 5,
borderColor: '#06d6cc',
borderWidth: 2,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#06d6cc',
fontWeight: '700',
fontSize: 16,
},
})
Contact.js code
import React, { useState, useEffect, useContext } from "react";
import {
StyleSheet,
View,
TextInput,Text
} from "react-native";
import { auth, firebase } from "./firebase";
import { List, Avatar, Divider, FAB } from "react-native-paper";
import uuid from "react-native-uuid";
import moment from "moment";
import { userContext } from "./UserContext";
import AsyncStorage from '#react-native-async-storage/async-storage';
const Contacts = () => {
const [username, setUsername] = useState("");
const value = useContext(userContext);
const [contactList, setContactList] = useState([{}]);
const [lastUser, setLastUser] = useState('');
useEffect(() => {
setContactList([])
updateLastUserName();
getContacts();
}, [])
useEffect(() => {
console.log(lastUser);
console.log(contactList);
}, [lastUser, contactList]);
async function updateLastUserName(){
const user = await getUserName();
setLastUser(user);
}
async function getUserName(){
const user = await AsyncStorage.getItem('sertacKul');
return user;
}
const addFriend = () => {
console.log(value.lastUser)
firebase
.database()
.ref("/users/")
.once("value")
.then((data) => {
let id = uuid.v4();
firebase
.database()
.ref("/friendrelations/" + id)
.set({
id: id,
user1: username,
user2: lastUser,
relationtype: "normal",
createdDate: moment().format("DD/MM/YYYY HH:mm:ss"),
})
.then(() => alert("Friend added."));
});
};
async function getContacts(){
await firebase.database().ref().child('friendrelations').orderByChild('user2').equalTo(lastUser)
.once('value').then(data => {
data.forEach((node) => { setContactList(lastContacts => [...lastContacts, node.val().user1])})
})
}
return (
<View>
<TextInput
placeholder="Yeni Arkadaş"
value={username}
style={styles.input}
onChangeText={(text) => setUsername(text)}
/>
<FAB
onPress={() => addFriend()}
icon="plus"
style={{ position: "absolute", right: 16 }}
/>
{/* is not working */}
{contactList.map((item)=>{
(<List.Item onPress={() => navigation.navigate('Conversation')} title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
)
})}
<Divider inset/>
</View>
);
};
export default Contacts;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
},
logo: {
resizeMode: "contain",
width: "100%",
marginBottom: 40,
},
inputContainer: {
width: "80%",
},
input: {
backgroundColor: "#eeeeee",
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: "60%",
justifyContent: "center",
alignItems: "center",
marginTop: 40,
},
button: {
backgroundColor: "#06d6cc",
width: "100%",
padding: 15,
borderRadius: 10,
alignItems: "center",
},
buttonOutline: {
backgroundColor: "white",
marginTop: 5,
borderColor: "#06d6cc",
borderWidth: 2,
},
buttonText: {
color: "white",
fontWeight: "700",
fontSize: 16,
},
buttonOutlineText: {
color: "#06d6cc",
fontWeight: "700",
fontSize: 16,
},
});
The arrow function has a function body and neglects to return any value that is being mapped to. Don't forget to also specify a unique React key for the mapped components/elements.
{contactList.map((item) => {
return (
<List.Item
key={item.id}
onPress={() => navigation.navigate('Conversation')}
title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
);
})}
Or remove the body so there's an implicit return.
{contactList.map((item) => (
<List.Item
key={item.id}
onPress={() => navigation.navigate('Conversation')}
title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
))}

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

React Native Navigation (ver4.x) unable to get props in custom header component. Keep getting undefined error

I have a custom header in my app and I am trying to get the navigation to open the Drawer when clicked on the menu item in the header component. I've passed the navigation and the header text as props to the component. However the props are being returned as undefined.
This is my header
import React from 'react';
import {View, StyleSheet, Text, Image, Alert, TouchableOpacity } from 'react-native';
import Colors from '../constants/Colors';
import { MaterialIcons } from '#expo/vector-icons';
const Header = ({navigation, headerText}) => {
const openMenu = () => {
console.log({headerText}) **/// this prints Object { "headerText": undefined,}**
navigation.openDrawer() **/// this also throws an undefined error**
}
console.log(headerText)**/// this displays the headerText correct on loading**
return (
<View style={styles.header} >
<MaterialIcons onPress={openMenu} name='menu' size={30} style={styles.icon} />
<Text style={styles.logo}>My Home Page Header</Text>
</View>
);
};
const styles = StyleSheet.create({
header: {
paddingTop: 20,
width: '100%',
height: '10%',
flexDirection: 'row',
},
logo: {
height: '100%',
width: '90%',
fontFamily: 'pacifico-regular',
fontSize: 28,
paddingTop: 20,
paddingLeft: 20,
},
icon: {
marginTop:30,
paddingLeft: 10,
},
});
export default Header;
console.log(headerText)/// this displays the header text correctly when loading the component.
However trying to use the props in the Text or the View throws an undefined error.
Clicking on the MaterialIcon menu icon gives the error :
Object {
"headerText": undefined,
}
and
TypeError: undefined is not an object (evaluating 'navigation.openDrawer')
This is the homestack.js
import { createStackNavigator } from 'react-navigation-stack';
import NewFeaturedRecipes from '../screens/NewFeaturedRecipes';
import NewRecipeDetails from '../screens/NewRecipeDetails';
import Header from '../shared/Header';
import React from 'react';
import {navigation} from 'react-navigation'
// const navigation = navigation;
const screens = {
NewFeaturedRecipes: {
screen: NewFeaturedRecipes,
navigationOptions: ({navigation}) => {
return {
headerTitle: () => <Header navigation={navigation}
headerText='Testting headertext from hoomestack' />
}
}
},
NewRecipeDetails: {
screen: NewRecipeDetails,
navigationOptions: {
title: 'Recipe Details',
}
},
}
const HomeStack = createStackNavigator(screens, {
defaultNavigationOptions: {
headerStyle: {
height: 20,
},
}
});
export default (HomeStack);
Here the answer if anybody is interested. I've used React Navigation 5.x for the nested navigators and I am able to call the openDrawer() from the menu in the Header component.
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Button, DrawerLayoutAndroid } from 'react-native';
import { NavigationContainer, useNavigation } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import {createDrawerNavigator} from '#react-navigation/drawer';
import { MaterialIcons } from '#expo/vector-icons';
const Header = ({ headerText }) => {
const navigation = useNavigation()
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', flexDirection: 'row' }}>
<MaterialIcons onPress={()=> navigation.openDrawer()} name='menu' size={30} style={styles.icon} />
<Text>Header Text = {headerText}</Text>
</View>
)
}
const HomeScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button onPress={() => navigation.navigate('Details')} title='Goto Details Screen' />
</View>
)
}
const DetailScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Detail Screen</Text>
<Button onPress={() => navigation.navigate('Home')} title='Goto Home Screen' />
</View>
)
}
const HomeStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name='Home'
component={HomeScreen}
options={{
headerTitle: props => <Header headerText='Text from App' />
}}
/>
<Stack.Screen name='Details' component={DetailScreen} options={{
headerTitle: props => <Header headerText='Text from Details' />
}}
/>
</Stack.Navigator>
)
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', flexDirection:'column' }}>
<Text>Notifications Screen</Text>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Stack = createStackNavigator()
const Drawer = createDrawerNavigator()
const App = () => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName='Home'>
<Drawer.Screen name='Home' component={HomeStack}/>
<Drawer.Screen name='Notifications' component={NotificationsScreen}/>
</Drawer.Navigator>
</NavigationContainer>
)
}
export default App
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});

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