I am having issues when a user signs up using firebase auth, I am unable to capture the username so that it can be used in other parts of the app.
The error that i see in the console is:
"Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field displayName in document"...)
Would really appreciate if someone can point me to where the mistake is. Here are my files:
AuthProvider.js
import React, { createContext, useState } from "react";
import { auth, db } from "../firebase";
export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AuthContext.Provider
value={{
user,
setUser,
login: async (email, password) => {
try {
await auth.signInWithEmailAndPassword(email, password);
} catch (e) {
console.log(e);
}
},
register: async (email, password, display_name) => {
try {
await auth
.createUserWithEmailAndPassword(email, password)
.then(async (res) => {
const userInfo = {
displayName: display_name,
};
await db
.collection("users")
.doc(res.user.uid)
.set(userInfo)
.then(() => {
console.log("user added")
console.log(res);
});
});
} catch (e) {
console.log(e);
}
},
logout: async () => {
try {
await auth.signOut();
} catch (e) {
console.log(e);
}
},
}}
>
{children}
</AuthContext.Provider>
);
};
SignUpScreen.js
import React, { useContext, useState } from "react";
import {
View,
Text,
TouchableOpacity,
Image,
Platform,
StyleSheet,
ScrollView,
Alert,
} from "react-native";
import FormInput from "../components/FormInput";
import FormButton from "../components/FormButton";
import SocialButton from "../components/SocialButton";
import { AuthContext } from "../navigation/AuthProvider";
const SignupScreen = ({ navigation }) => {
const [display_name, setDisplay_Name] = useState();
const [email, setEmail] = useState();
const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const { register } = useContext(AuthContext);
const registerCheck = () => {
if (
display_name != "" &&
email != "" &&
password != "" &&
confirmPassword != ""
) {
if (password == confirmPassword) {
register(email, password);
} else {
Alert.alert("Oops! Passwords did not match");
}
} else {
Alert.alert("Oops! Some information is missing");
}
console.log(display_name, email, password, confirmPassword);
};
return (
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.text}>Create an Account</Text>
<FormInput
labelValue={display_name}
onChangeText={(userDisplay_Name) => setDisplay_Name(userDisplay_Name)}
placeholderText="Name"
iconType="user"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<FormInput
labelValue={email}
onChangeText={(userEmail) => setEmail(userEmail)}
placeholderText="Email"
iconType="user"
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<FormInput
labelValue={password}
onChangeText={(userPassword) => setPassword(userPassword)}
placeholderText="Password"
iconType="lock"
secureTextEntry={true}
/>
<FormInput
labelValue={confirmPassword}
onChangeText={(userConfirmPassword) =>
setConfirmPassword(userConfirmPassword)
}
placeholderText="Confirm Password"
iconType="lock"
secureTextEntry={true}
/>
<FormButton
buttonTitle="Sign Up"
onPress={() => registerCheck(email, password)}
/>
<View style={styles.textPrivate}>
<Text style={styles.color_textPrivate}>
By registering, you confirm that you accept our{" "}
</Text>
<TouchableOpacity onPress={() => alert("Terms Clicked!")}>
<Text style={[styles.color_textPrivate, { color: "#e88832" }]}>
Terms of service
</Text>
</TouchableOpacity>
<Text style={styles.color_textPrivate}> and </Text>
<Text style={[styles.color_textPrivate, { color: "#e88832" }]}>
Privacy Policy
</Text>
</View>
<SocialButton
buttonTitle="Sign Up with Facebook"
btnType="facebook"
color="#4867aa"
backgroundColor="#e6eaf4"
onPress={() => {}}
/>
<SocialButton
buttonTitle="Sign Up with Google"
btnType="google"
color="#de4d41"
backgroundColor="#f5e7ea"
onPress={() => {}}
/>
<TouchableOpacity
style={styles.navButton}
onPress={() => navigation.navigate("Login")}
>
<Text style={styles.navButtonText}>Have an account? Sign In</Text>
</TouchableOpacity>
</ScrollView>
);
};
export default SignupScreen;
const styles = StyleSheet.create({
container: {
backgroundColor: "#f9fafd",
flex: 1,
justifyContent: "center",
alignItems: "center",
padding: 20,
},
text: {
fontFamily: "Helvetica",
fontSize: 28,
marginBottom: 10,
color: "#051d5f",
},
navButton: {
marginTop: 15,
},
navButtonText: {
fontSize: 18,
fontWeight: "500",
color: "#2e64e5",
fontFamily: "Helvetica",
},
textPrivate: {
flexDirection: "row",
flexWrap: "wrap",
marginVertical: 35,
justifyContent: "center",
},
color_textPrivate: {
fontSize: 13,
fontWeight: "400",
fontFamily: "Helvetica",
color: "grey",
},
});
Related
I have been encountering an error when trying to use Firebase's SignIn With google auth method. So far I have:
Enabled the google auth method in my admin console
Looked at the docs for it and implemented the requirements
Enabled, and correctly got the Email/Password auth to work
I am trying to use the signInWithPopup method instead of a redirect.
Here is the SignIn.js code file:
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, TextInput, Pressable } from 'react-native';
import tw from 'tailwind-react-native-classnames';
import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { auth, provider } from "../firebaseConfig";
import { Ionicons } from '#expo/vector-icons';
import { Feather } from '#expo/vector-icons';
import SignInHeader from '../components/SignInHeader';
export default function SignIn({ navigation }) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
let signInWithGoogle = () => {
signInWithPopup(auth, provider)
.then((result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
const token = credential.accessToken;
const user = result.user;
navigation.navigate("Home");
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
const email = error.customData.email;
const credential = GoogleAuthProvider.credentialFromError(error);
console.log(errorCode, errorMessage, email, credential);
});
}
let signIn = () => {
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
const user = userCredential.user;
navigation.navigate("Home");
console.log(user);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorCode, errorMessage);
switch (errorCode) {
case "auth/invalid-email":
alert("Please Enter a valid email address");
break;
case "auth/user-not-found":
alert("User not found");
break;
case "auth/wrong-password":
alert("Incorrect Password. Try again.");
break;
case "auth/internal-error":
alert("Please enter a valid password");
break;
}
});
}
return (
<>
<SignInHeader />
<View style={{ alignItems: 'center', marginTop: '25%', paddingTop: 10 }}>
<View style={styles.searchSection}>
<Ionicons name="mail-outline" size={20} color="black" style={styles.searchIcon} />
<TextInput
style={styles.input}
placeholder="Email"
onChangeText={text => setEmail(text)}
value={email}
clearButtonMode="always"
/>
</View>
<View style={{ padding: 25 }}>
<View style={styles.searchSection}>
<Feather name="lock" size={20} color="black" style={styles.searchIcon} />
<TextInput
style={styles.input}
placeholder="Password"
onChangeText={text => setPassword(text)}
value={password}
secureTextEntry={true}
clearButtonMode="always"
/>
</View>
</View>
<Pressable style={{ marginLeft: '55%', marginTop: -10 }} onPress={() => navigation.navigate("ResetPassword")}>
<Text style={{ color: '#cdcdcd' }}>Forgot Password?</Text>
</Pressable>
<Pressable onPress={signIn} style={({ pressed }) => [
{
backgroundColor: pressed
? '#34AE65'
: '#64DA93'
},
styles.notPressed,
]}>
<Text style={{ fontFamily: "OpenSans_600SemiBold", fontSize: 20, color: 'white' }}>Log In</Text>
</Pressable>
<Pressable onPress={signInWithGoogle} style={({ pressed }) => [
{
backgroundColor: pressed
? '#34AE65'
: '#64DA93'
},
styles.notPressed,
]}>
<Text style={{ fontFamily: "OpenSans_600SemiBold", fontSize: 20, color: 'white' }}>Log In with Google</Text>
</Pressable>
<Pressable onPress={() => navigation.navigate("SignUp")}>
<Text style={{ flex: 1, color: '#cdcdcd', marginTop: 20, flexDirection: 'row' }}>Don't have and account?<Text style={{ color: 'grey' }}> Sign Up</Text></Text>
</Pressable>
</View >
</>
);
}
const styles = StyleSheet.create({
searchSection: {
flexDirection: 'row',
alignItems: 'center',
width: 360,
height: 45,
borderBottomColor: '#64DA93',
borderBottomWidth: 2,
},
searchIcon: {
padding: 1,
},
input: {
flex: 1,
paddingTop: 10,
paddingRight: 10,
paddingBottom: 10,
paddingLeft: 10,
},
notPressed: {
height: 45,
width: 360,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 10,
marginTop: 50
}
});
Next, which is important is my firebaseConfig.js code file:
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
const firebaseConfig = {
apiKey: "xx",
authDomain: "xx",
projectId: "xx",
storageBucket: "xx",
messagingSenderId: "xx",
appId: "xx",
measurementId: "xx"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const provider = new GoogleAuthProvider();
export { auth, provider };
This is the error:
ERROR TypeError: (0, _auth.signInWithPopup) is not a function. (In '(0, _auth.signInWithPopup)(_firebaseConfig.auth, _firebaseConfig.provider)', '(0, _auth.signInWithPopup)' is undefined)
Thanks for the help.
signInWithPopup is not supported in React Native. Use auth().signInWithCredential(googleCredential) instead.
Upon successful sign-in, any onAuthStateChanged listeners will trigger with the new authentication state of the user.
Consider using this library instead as the one you are using is really meant for the web
I'm new to React Native and currently trying to integrate Deso Identity into my React Native App.
Question: How should I retrieve user data if I use WebView and what is the correct implementation to generate derived key?
Goal:
Navigate to Deso Identity Page when clicking on a button from LogIn screen
Receive derived key and all user response data after logging in
What I have tried:
I'm currently trying to generate derive key by making a call to Deso's window API without using WebView
I have tried using WebView with a DesoLogin.js component below but there's not much details from Deso's documentation and I was not able to retrieve response data after logging in
DesoLogin.js
import React, { useState, useEffect } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useNavigation } from '#react-navigation/native';
import Home from '../screens/Home';
const DesoLogin = () =>{
const navigation = useNavigation();
// const webView = WebView();
const [signIn, setSignIn] = useState(false)
const [userProfile, setUserProfile] = useState(null)
// function onMessage(data) {
// alert(data.nativeEvent.data);
// }
// const handleLogin = (e) => {
// const data = webView.getUrl(e);
// setUserProfile(data)
// }
const handleNavigationStateChange = () => {
navigation.navigate("Home", {userProfile});
}
const onNavigationStateChange = e => {
if (userProfile!==e.url) {
console.log(e.url);
setUserProfile(e.url);
console.log(userProfile);
}
};
useEffect(() => {
setSignIn(true);
if (userProfile) {
handleNavigationStateChange();
}
},[userProfile])
return (
<SafeAreaView style={{ flex: 1 }}>
<WebView
source={{
uri: 'https://identity.deso.org/derive?callback=auth://derive'
}}
// onMessage={onMessage}s
// injectedJavaScript={handleLogin}
onNavigationStateChange={onNavigationStateChange}
javaScriptEnabled
style={{ marginTop: 20 }}
/>
</SafeAreaView>
);
}
export default DesoLogin;
Error:
I know that windows.open() doesn't work in react native like it does in web application
Deso Mobile Integration Doc
Window API-Callbacks section
Login.js Screen code below
import React, { useEffect, useState } from "react";
import { useNavigation } from "#react-navigation/native";
import axios from 'axios';
import DesoLogin from "../components/DesoLogin";
import DesoIdentity from "../libs/DesoIdentity";
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'
import { COLORS, FONTS, SIZES, SHADOWS, assets } from "../constants";
import { CircleButton, RectButton, DetailsDesc, DetailsBid, FocusedStatusBar } from "../components";
const LogIn = () => {
const [loading, setLoading] = useState(null);
const [error, setError] = useState(null);
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [publicKey, setSetPublicKey] = useState(null)
const [desoIdentity, setDesoIdentity] = useState(null)
const navigation = useNavigation()
useEffect(() => {
axios('https://identity.deso.org/derive?callback=auth://derive')
.then(response => {
setSetPublicKey(response.accessSignature)
})
.catch(error => {
console.error("Error Fetching data", error);
setError(error);
throw error;
})
} , [])
const handleSignUp = () => {
return 0;
}
const handleLogin = async () => {
setSetPublicKey(publicKey);
setLoggedIn(true);
}
const handleLogout = () => {
setSetPublicKey(null);
setLoggedIn(false);
}
return (
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<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}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default LogIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: COLORS.white,
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#0782F9',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: COLORS.white,
marginTop: 5,
borderColor: '#0782F9',
borderWidth: 2,
},
buttonText: {
color: COLORS.white,
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#0782F9',
fontWeight: '700',
fontSize: 16,
},
})
I'm using React Native Expo. Currently i'm trying to make an application which uses a barcodescanner for scanning QR-code objects. I've implemented a turn camera button for the front or back camera but when i press the button it does nothing only when i switch from one screen to the other. I think there is something wrong with refreshing the screen immediately but i've no clue of how i should solve this problem
Code:
import React, { useEffect, useState, useLayoutEffect } from 'react';
import { StyleSheet, Text, View, Button, Alert, ActivityIndicator, Pressable } from 'react-native';
import { globalStyles } from '../styles/global';
// import { Camera, BarCodeScanningResult } from 'expo-camera';
import { BarCodeScanner } from 'expo-barcode-scanner';
import BarcodeMask from 'react-native-barcode-mask';
import { useIsFocused, useNavigation } from '#react-navigation/native';
import CustomButton from '../components/CustomButton';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
export function ShowLoading(){
return(
<View style={styles.loader}><ActivityIndicator size="large" color='white'/></View>
)
}
export default function Scan(){
const navigation = useNavigation()
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [loading, setLoading] = useState(false);
const [type, setType] = useState(BarCodeScanner.Constants.Type.back);
const isFocused = useIsFocused()
useEffect(() => {
(async () => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
// useEffect(() => {
// if(loading){
// setLoading(true)
// } else {
// setLoading(false)
// }
// },[loading])
const initScanner = async() => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
}
const handleNavigation = async() => {
setScanned(false)
navigation.navigate('Oefening')
}
const handleNo = () => {
setScanned(false)
}
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true)
setLoading(true)
setTimeout(() => { Alert.alert(
'QR-Code gevonden',
`QR-Code met type ${type} en data ${data} is gescand, wilt u verder gaan?`,
[
{
text: "Nee",
onPress: () => handleNo(),
},
{
text: "Ja",
onPress: () => handleNavigation(),
}
]
), setLoading(false)}, 1000)
}
if (hasPermission === null) {
return <View style={styles.permissionWrapper}>
<Text style={styles.permissionText}>Een moment geduld..</Text>
<ActivityIndicator size='large' color='#1f69b1'></ActivityIndicator>
</View>;
}
if (hasPermission === false) {
return <Text>Geen toegang tot uw camera!</Text>;
}
return (
<View style={{flex: 1, flexDirection: 'column', justifyContent: 'flex-end'}}>
{loading? (<View style={styles.loader}><ActivityIndicator size='large' color='#1f69b1'></ActivityIndicator></View>
) : (
isFocused &&
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
type={type}
>
<View style={styles.topOptions}>
<View style={styles.cameraRotateWrapper}>
<Pressable style={styles.cameraRotate}
onPress={() => {
setType(
type === BarCodeScanner.Constants.Type.back
? BarCodeScanner.Constants.Type.front
: BarCodeScanner.Constants.Type.back
);
}}
>
<Icon name='rotate-3d-variant' size={40} color={'white'}></Icon>
</Pressable>
</View>
</View>
<BarcodeMask edgeColor={'#62B1F6'} showAnimatedLine={true}/>
</BarCodeScanner>)}
{scanned? <View style={styles.searchTextWrapper}><Text style={styles.searchText}>Gevonden!</Text></View> : <View style={styles.searchTextWrapper}><Text style={styles.searchText}>Zoeken naar QR-Code.... </Text></View>}
{/* {scanned? <Button title={'Opnieuw scannen'} onPress={() => setScanned(false)} /> : null} */}
<View style={styles.bottomOptions}>
<CustomButton textValue="Herladen" onPress={initScanner}></CustomButton>
</View>
</View>
)
}
const styles = StyleSheet.create({
loader: {
justifyContent: "center",
alignItems: 'center',
},
permissionWrapper: {
justifyContent: 'center',
alignItems:'center',
margin: 15,
},
permissionText: {
fontSize: 16,
fontWeight: 'bold',
},
topOptions: {
marginTop: 20,
justifyContent: 'space-between',
marginHorizontal: '10%'
},
searchTextWrapper: {
},
searchText: {
color: 'white',
fontSize: 18,
textAlign: 'center',
},
cameraRotateWrapper: {
width: 50,
height: 50,
},
cameraRotate: {
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: "white",
backgroundColor: '#1f69b1',
borderRadius: 10,
},
bottomOptions: {
marginHorizontal: '10%',
marginBottom: 10,
},
})
I recently have been making a app for my IOS app and am introducing firebase email/password auth to my project. The registration part works good but when i do the handleSignin function it doesnt quite work as expected. Any ideas why
my code:
import React from 'react';
import { Button,StyleSheet,View,Text, Image,SafeAreaView, TextInput, KeyboardAvoidingView, TouchableOpacity} from 'react-native';
import {auth} from "../firebase"
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword} from "firebase/auth";
import { FirebaseError } from 'firebase/app';
export const Login = () => {
const [email, setEmail] = React.useState("")
const [password, setPassword] = React.useState("")
const handleSignUp = (e) => {
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});
}
const handleLogin = () => {
auth
.signInWithEmailAndPassword(email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with:', user.email);
})
.catch(error => alert(error.message))
}
return (
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<Text style={styles.heading}>Unlock the power of time managment</Text>
<View style={styles.inputContainer}>
<TextInput
value={email}
placeholder="Email"
style={styles.input}
onChangeText={text => setEmail(text)}
/>
<TextInput
placeholder="Password"
style={styles.input}
onChangeText={text => setPassword(text)}
value={password}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={handleLogin}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.buttonOutline]}
onPress={handleSignUp}
>
<Text style={styles.buttonOutlineText} >Register</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: 'white',
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
heading: {
fontSize: 30,
fontWeight: "700"
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#0782F9',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: 'white',
marginTop: 5,
borderColor: '#0782F9',
borderWidth: 2,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#0782F9',
fontWeight: '700',
fontSize: 16,
},
});
expo go error:
firebase.auth.signinwithemailandpassword not a function
firebase.auth.signinwithemailandpassword returned undefined
You're using the new, modular SDK syntax, where most functionality is exposed as a top-level function, instead of as a method on an object. When you call createUserWithEmailAndPassword as a top-level function you pass in the auth object, and you need to do the same for signing in:
const handleLogin = () => {
signInWithEmailAndPassword(auth, email, password)
...
I recommend keeping the Firebase documentation handy when troubleshooting problems like this, as the above is almost exactly the code shown in the Web version 9 (modular) tab in the section signing in a user with an email address and password
Below is the guideline on what worked for me, you can try it.
Here is the explanation:
You have to import signInWithEmailAndPassword from firebase/auth.
Note: signInWithEmailAndPassword is a function that takes three arguments, ie auth, email and password.
import { signInWithEmailAndPassword } from "firebase/auth";
const signIn= (e) => {
e.preventDefault();
// for login
signInWithEmailAndPassword(auth, email, password).then((auth) => {
console.log(auth);
if (auth) {
// if successfully signed in, redirect the new user to the home page
navigate('/');
}
}).catch(error => alert(error.message));
};
This is probably a dumb question, but I've been following some react native / expo tutorials on how to make a login screen with Firebase. The tutorial I followed also made a loading screen (using a loading state) that will display while Firebase is connecting. Unfortunately, the loading state never ends for me, and I don't know how to fix it.
Here is my Navigator.js file:
import React, { useReducer } from "react";
import { View, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from "#react-navigation/stack";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { AuthContext } from '../contexts/UserContext';
import { firebase } from "../utils/FirebaseConfig";
import Login from "../screens/Login";
import Signup from "../screens/Signup";
import Home from "../screens/Home";
const Drawer = createDrawerNavigator();
const RootStack = createStackNavigator();
export default AppNavigation = (props) => {
const initialLoginState = {
isLoading: true,
user: null,
};
const loginReducer = (prevState, action) => {
switch (action.type) {
case 'LOGIN':
return {
...prevState,
user: action.user,
isLoading: false,
};
case 'LOGOUT':
return {
...prevState,
user: null,
isLoading: false,
};
case 'REGISTER':
return {
...prevState,
user: action.user,
isLoading: false,
};
}
};
const [loginState, dispatch] = useReducer(loginReducer, initialLoginState);
const authContext = React.useMemo(() => ({
signIn: async (email, password) => {
return firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(async (userCred) => {
dispatch({ type: 'LOGIN', user: userCred.user });
return true;
}).catch((error) => {
if (error.code === "auth/user-disabled") {
alert("User disabled!");
}
if (error.code === "auth/invalid-email") {
alert("That email address is invalid!");
}
if (error.code === "auth/user-not-found") {
alert("User not found, please sign up!");
}
if (error.code === "auth/wrong-password") {
alert("Wrong password!");
}
return false;
})
},
signOut: async () => {
return firebase.auth().signOut().then(async () => {
dispatch({ type: 'LOGOUT' });
});
},
signUp: (email, password) => {
return firebase.auth().createUserWithEmailAndPassword(email, password).then((userCred) => {
dispatch({ type: 'REGISTER', user: userCred.user });
}).catch((error) => {
if (error.code === "auth/email-already-in-use") {
alert("That email address is already in use!");
}
if (error.code === "auth/invalid-email") {
alert("That email address is invalid!");
}
if (error.code === "auth/operation-not-allowed") {
alert("Operation is not allowed!");
}
if (error.code === "auth/weak-password") {
alert("The password is too weak!");
}
return false;
})
}
}), []);
if (loginState.isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="grey" />
</View>
);
}
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer>
{loginState.user !== null ? (
<Drawer.Navigator >
<Drawer.Screen name="Home" user={loginState.user} component={Home} />
</Drawer.Navigator>
) :
(
<RootStack.Navigator headerMode='none'>
<RootStack.Screen name="Login" component={Login} />
<RootStack.Screen name="Signup" component={Signup} />
</RootStack.Navigator>
)
}
</NavigationContainer>
</AuthContext.Provider>
)
}
Here is my Home.js File:
import React from 'react';
import { useContext } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { AuthContext } from "../contexts/UserContext";
function Home(props) {
const { signOut } = useContext(AuthContext);
return (
<View style={{ flex: 1 }}>
<Text>Welcome</Text>
<Text>Email: {props.user?.email}</Text>
<Text>uid: {props.user?.uid}</Text>
<Text>displayName: {props.user?.displayName}</Text>
<Text>photo: {props.user?.photoURL}</Text>
<TouchableOpacity onPress={() => signOut()} style={{ flexDirection: "row", alignItems: "center", justifyContent: "center", width: "100%" }} >
<Text style={{ fontWeight: "bold", fontSize: 18 }}>Logout</Text>
</TouchableOpacity>
</View>
);
}
export default Home;
Here is the Login.js file:
import React, { useContext, useState } from 'react';
import { KeyboardAvoidingView, View, Text, TextInput } from 'react-native';
import { AuthContext } from "../contexts/UserContext";
function Login(props) {
const [data, setData] = useState({
email: "",
password: ""
})
const { signIn } = useContext(AuthContext);
const emailInputChange = (val) => {
setData({
...data,
email: val
})
}
const passwordChange = (val) => {
setData({
...data,
password: val
});
}
const LoginHandle = () => {
signIn(data.email, data.password)
}
return (
<KeyboardAvoidingView>
<View style={{ flex: 1 }}>
<Text>Email: </Text>
<View >
<TextInput
placeholder="Email"
autoCapitalize="none"
onChangeText={(val) => emailInputChange(val)}
/>
</View>
<Text>Password: </Text>
<View>
<TextInput
placeholder="Password"
autoCapitalize="none"
secureTextEntry={true}
onChangeText={(val) => passwordChange(val)}
/>
</View>
<TouchableOpacity onPress={() => LoginHandle()} style={{ width: "100%", height: 50, justifyContent: "center", alignItems: "center", borderRadius: 10 }}>
<Text style={{ color: "#FFF", fontSize: 18, fontWeight: "bold" }}>Login</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
export default Login;
And finally, the Signup.js file:
import React, { useContext, useState } from 'react';
import { KeyboardAvoidingView, View, Text, TextInput } from 'react-native';
import { AuthContext } from "../contexts/UserContext";
function Signup(props) {
const [data, setData] = useState({
email: "",
password: ""
})
const { signUp } = useContext(AuthContext);
const emailInputChange = (val) => {
setData({
...data,
email: val
})
}
const passwordChange = (val) => {
setData({
...data,
password: val
});
}
const SignupHandle = () => {
signUp(data.email, data.password)
}
return (
<KeyboardAvoidingView>
<View style={{ flex: 1 }}>
<Text>Email: </Text>
<View >
<TextInput
placeholder="Email"
autoCapitalize="none"
onChangeText={(val) => emailInputChange(val)}
/>
</View>
<Text>Password: </Text>
<View>
<TextInput
placeholder="Password"
autoCapitalize="none"
secureTextEntry={true}
onChangeText={(val) => passwordChange(val)}
/>
</View>
<TouchableOpacity onPress={() => SignupHandle()} style={{ width: "100%", height: 50, justifyContent: "center", alignItems: "center", borderRadius: 10 }}>
<Text style={{ color: "#FFF", fontSize: 18, fontWeight: "bold" }}>Signup</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
);
}
export default Signup;