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

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.

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}/>}
/>
))}

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

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;
}

React navigation hide drawer item

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);

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 .

react native how to pass this.state to tabBarComponent

I customize TabBarCompenet and trying to pass cart value so that could keep updated cart on value change. But app throws error
Undefined is not an object '_this.state.cartAmount'
App.js
var {height, width} = Dimensions.get('window');
const DashboardTabNavigator = createBottomTabNavigator({
Tab1: {screen: FoodCategoryStack},
Tab2: {screen: EventsStack}
},
{
tabBarComponent:({ props }) => (
<AddTabButton {...props} cartAmount={this.state.cartAmount} />
)});
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
header: null,
headerLeft: <MaterialIcons
onPress={() => navigation.openDrawer()}
style={{ paddingLeft: 10 }}
name="menu"
size={30}
/>
};
}
}
);
const CustomDrawerComponent = (props) => (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ height: 150, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center', marginTop: 20 }}>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
)
const AppDrawerNavigator = createDrawerNavigator({
Home: {
screen: DashboardStackNavigator,
},
Events: {
screen: EventScreen
}
},
{
contentComponent: CustomDrawerComponent,
drawerWidth: width * 0.85
});
const AppSwitchNavigator = createSwitchNavigator({
Welcome: { screen: splashScreen },
Dashboard: { screen: AppDrawerNavigator }
});
const AppContainer = createAppContainer(AppSwitchNavigator);
export default class App extends React.Component {
constructor(props){
super(props)
this.state = {
cartAmount: '18.50'
}
}
componentWillMount() {
console.log('componentWillMount Tab View')
}
componentDidMount() {
console.log('componentDidMount Tab View')
console.log(this.state.cartAmount)
}
HandleTabPressOne () {
console.log('Cart function called')
this.setState({ cartAmount: '12.20' });
alert(this.state.cartAmount)
}
render() {
return ( <AppContainer{...this.props} />);
}
}
AddTabButton.js
import React, {Component} from 'react';
import {StyleSheet, Animated, Text, TouchableOpacity, View, Dimensions} from "react-native";
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
var {height, width} = Dimensions.get('window');
const AddTabButton = (props) => {
return (
<View style={{flex: 0.1, backgroundColor: '#FF0000', borderColor: '#FF0000', borderWidth: 1}}>
<View style={{flexDirection:'row', justifyContent: 'space-around', alignItems: 'center', paddingTop: 5}}>
<TouchableOpacity onPress={() => navigation.navigate('Tab1')} style={{alignItems: 'center', marginLeft: 5}}>
<MaterialIcons name="local-pizza" size={24} color="#FFFFFF" />
<Text style={styles.textFAB}>Menu</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.HandleTabPressOne}style={{alignItems: 'center'}}>
<MaterialIcons name="event-available" size={24} color="#FFFFFF" />
<Text style={styles.textFAB}>Event</Text>
</TouchableOpacity>
<View style={styles.cartFAB}>
<MaterialIcons name="shopping-basket" size={24} color="#FFFFFF" style={{marginTop: 10}} />
<Text style={styles.totalCart}>$ {(this.props.cartAmount != null) ? this.props.cartAmount : '12.55'}</Text>
</View>
</View>
</View>
);
};
export default AddTabButton;
As per suggestion of Andrew I implemented redux to overcome the scenario.

Resources