登录 Firebase React Native Expo 后无法获取用户数据



我正在尝试用React Native/Expo和Firebase创建一个社交媒体应用程序,我已经成功地创建了帐户和登录,但我仍在尝试如何在用户登录时获取用户名等用户数据。基本上,当我登录或创建帐户时,我希望个人资料页面显示与登录用户相关的用户名和个人资料图片,但我不知道如何做到这一点。它可能与AuthStateChanged((函数或类似的东西有关,但我不确定。

这是我的App.js文件:

import 'react-native-gesture-handler';
import React, { useState } from 'react';
import { LogBox, Text, View } from 'react-native';
import AppLoading from 'expo-app-loading';
import * as Font from 'expo-font';
import Feather from '@expo/vector-icons/Feather'
import { useFonts, Nunito_400Regular as NunitoRegular, Nunito_700Bold as NunitoBold } from '@expo-google-fonts/nunito';
import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
import Navigator from './src/navigation/index';
import * as firebase from "firebase";
import "firebase/auth";
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "AIzaSyB1TxcRpLQq0Zqs0f0FvPitIto0tZo_0xM",
authDomain: "shutter-42e70.firebaseapp.com",
projectId: "shutter-42e70",
storageBucket: "shutter-42e70.appspot.com",
messagingSenderId: "149059508529",
appId: "1:149059508529:web:0dbc5bbbb75bf022ef7810"
};
if (firebase.apps.length === 0) {
firebase.initializeApp(firebaseConfig);
}
// The theme we'll be using for our navigator
const MyTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: '#FAFAFA'
},
};
// Loads the Feather icons (https://docs.expo.io/guides/icons/)
function cacheFonts(fonts) {
return fonts.map(font => Font.loadAsync(font));
}
export default function App() {
const [assetsReady, setAssetsReady] = useState(false);
async function _loadFonts() {
const iconFontAssets = cacheFonts([Feather.font])
await Promise.all([...iconFontAssets]);
}
// Loads the Nunito font (https://docs.expo.io/guides/using-custom-fonts/)
let [fontsLoaded] = useFonts({
NunitoRegular, NunitoBold
});
// If the fonts or assets are not loaded, we show a default App Loading screen.
// Otherwise, we return our Photo Sharing App!
if (!fontsLoaded || !assetsReady) {
return <AppLoading
startAsync={_loadFonts}
onFinish={() => setAssetsReady(true)}
onError={console.warn}
/>
}
return (
<NavigationContainer theme={MyTheme}>
<Navigator />
</NavigationContainer>
);
}

这是我的Login.js文件:

import React from 'react';
import { StyleSheet, View, Text, Image, TextInput, TouchableOpacity } from 'react-native';
import theme from '../../assets/themes';
import { Formik } from 'formik';
import { Octicons, Fontisto } from '@expo/vector-icons';
import Separator from './Separator';
import KeyBoardAvoidingWrapper from './KeyboardAvoidingWrapper';
import firebase from 'firebase';
var errorMsg = '...'
const Login = ({navigation}) => {
return (
<KeyBoardAvoidingWrapper>
<View>
<View style = {styles.StyledContainer}>
<View style = {styles.InnerContainer}>
<Image style = {styles.PageLogo} resizeMode = "cover" source = {require('./../../assets/images/logo.png')} />
<Text style = {styles.PageTitle}>Shutter</Text>
<Text style = {styles.TagLine}>Social Media for Photographers</Text>
</View>
</View>
<Formik
initialValues = {{email: '', password: ''}}
onSubmit = {(values) => {
firebase.auth().signInWithEmailAndPassword(values.email, values.password)
.then((result) => {
navigation.navigate('Feed');
})
.catch((error) => {
alert(error)
})
}}
>
{({handleChange, handleBlur, handleSubmit, values}) => (
<View style = {styles.styledFormArea}>
<MyTextInput
label = " "
icon = "mail"
placeholder = "email@email.com"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('email')}
onBlur = {handleBlur('email')}
value = {values.email}
keyboardType = "email-address"
/>
<MyTextInput
label = " "
icon = "lock"
placeholder = "password"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('password')}
onBlur = {handleBlur('password')}
value = {values.password}
secureTextEntry = {true}
/>
<Text style = {styles.msgBox}>{errorMsg}</Text>
<TouchableOpacity onPress = {handleSubmit} style = {styles.loginButton}>
<Text style = {styles.loginButtonText}>Login</Text>
</TouchableOpacity>
<Separator />
<TouchableOpacity onPress = {handleSubmit} style = {styles.googleSigninButton}>
<Fontisto name = "google" color = {theme.colors.white} size = {25} ></Fontisto>
<Text style = {styles.googleSigninButtonText}>Sign in with Google</Text>
</TouchableOpacity>
<View style = {styles.signupLinkView}>
<Text style = {styles.signupText}>Don't have an account? </Text>
<TouchableOpacity style = {styles.signupLinkButton}>
<Text onPress = {() => navigation.navigate('Sign Up')} style = {styles.signupLinkText}>Sign up</Text>
</TouchableOpacity>
</View>
</View>
)}
</Formik>
</View>
</KeyBoardAvoidingWrapper>
);
};
const MyTextInput = ({label, icon, ...props}) => {
return (
<View>
<View style = {styles.leftIcon}>
<Octicons name = {icon} size = {30} color = {theme.colors.primary} />
</View>
<Text style = {styles.styledTextInput}>{label}</Text>
<TextInput style = {styles.textInput} {...props} />
</View>
)
}
const styles = StyleSheet.create({
StyledContainer: {
flex: 1,
padding: theme.spacing.m,
paddingTop: theme.spacing.l,
backgroundColor: theme.colors.white,
marginTop: 80,
},
InnerContainer: {
justifyContent: 'center',
alignItems: 'center',
},
PageLogo: {
width: 100,
height: 100,
},
PageTitle: {
...theme.textVariants.h1,
marginTop: theme.spacing.m,
},
TagLine: {
...theme.textVariants.body3,
},
styledFormArea: {
justifyContent: 'center',
marginHorizontal: theme.spacing.l,
borderRadius: theme.borderRadius.m,
marginTop: 40,
},
leftIcon: {
position: 'absolute',
zIndex: 1,
marginTop: 28,
marginLeft: 12,
},
styledTextInput: {
...theme.textVariants.body3,
},
textInput: {
backgroundColor: theme.colors.gray,
paddingVertical: 10,
paddingLeft: 50,
paddingRight: theme.spacing.l,
borderRadius: theme.borderRadius.m,
},
loginButton: {
backgroundColor: theme.colors.primary,
alignItems: 'center',
marginTop: 20,
paddingVertical: 8,
borderRadius: theme.borderRadius.m,
},
loginButtonText: {
...theme.textVariants.body2,
color: theme.colors.white,
},
msgBox: {
...theme.textVariants.body3,
alignSelf: 'center',
},
googleSigninButton: {
backgroundColor: theme.colors.primary,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: 16,
paddingVertical: 8,
borderRadius: theme.borderRadius.m,
},
googleSigninButtonText: {
...theme.textVariants.body2,
color: theme.colors.white,
paddingLeft: 25,
},
signupLinkView: {
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
padding: theme.spacing.sm,
},
signupText: {
...theme.textVariants.body3,
},
signupLinkButton: {
},
signupLinkText: {
...theme.textVariants.body3,
opacity: 0.6,
},
})
export default Login;

这是我的Signup.js文件:

import React from 'react';
import { StyleSheet, View, Text, Image, TextInput, TouchableOpacity } from 'react-native';
import theme from '../../assets/themes';
import { Formik } from 'formik';
import { Octicons } from '@expo/vector-icons';
import Separator from './Separator';
import KeyboardAvoidingWrapper from './KeyboardAvoidingWrapper';
import firebase from 'firebase';
var errorMsg = '...'
const SignUp = ({navigation}) => {
return (
<KeyboardAvoidingWrapper>
<View>

<View style = {styles.StyledContainer}>
<View style = {styles.InnerContainer}>
<Image style = {styles.PageLogo} resizeMode = "cover" source = {require('./../../assets/images/logo.png')} />
<Text style = {styles.PageTitle}>Shutter</Text>
<Text style = {styles.TagLine}>Social Media for Photographers</Text>
</View>
</View>
<Formik
initialValues = {{fullName: '', email: '', username: '', password: '', confirmPassword: ''}}
onSubmit = {(values) => {
firebase.auth().createUserWithEmailAndPassword(values.email, values.password)
.then((result) => {
firebase.firestore().collection("users")
.doc(firebase.auth().currentUser.uid)
.set({
fullName: values.fullName,
displayName: values.email,
username: values.username,
password: values.password,
})
if (values.password === values.confirmPassword)
navigation.navigate('Signup Options')
else
errorMsg = 'Passwords do not match'
})
.catch((error) => {
alert(error)
})
}}
>
{({handleChange, handleBlur, handleSubmit, values}) => (
<View style = {styles.styledFormArea}>
<MyTextInput
label = "Name"
icon = "person"
placeholder = "John Doe"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('fullName')}
onBlur = {handleBlur('fullName')}
value = {values.fullName}
/>
<MyTextInput
label = "Email"
icon = "mail"
placeholder = "email@email.com"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('email')}
onBlur = {handleBlur('email')}
value = {values.email}
keyboardType = "email-address"
/>

<MyTextInput
label = "Username"
icon = "person"
placeholder = "username"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('username')}
onBlur = {handleBlur('username')}
value = {values.username}
/>
<MyTextInput
label = "Password"
icon = "lock"
placeholder = "password"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('password')}
onBlur = {handleBlur('password')}
value = {values.password}
secureTextEntry = {true}
/>
<MyTextInput
label = "Confirm Password"
icon = "lock"
placeholder = "retype password"
placeholderTextColor = {theme.colors.black}
onChangeText = {handleChange('confirmPassword')}
onBlur = {handleBlur('confirmPassword')}
value = {values.confirmPassword}
secureTextEntry = {true}
/>
<Text style = {styles.msgBox}>{errorMsg}</Text>
<TouchableOpacity onPress = {handleSubmit} style = {styles.loginButton}>
<Text style = {styles.loginButtonText}>Sign Up</Text>
</TouchableOpacity>
<Separator />
<View style = {styles.signupLinkView}>
<Text style = {styles.signupText}>Already have an account? </Text>
<TouchableOpacity style = {styles.signupLinkButton}>
<Text onPress = {() => navigation.navigate('Login')} style = {styles.signupLinkText}>Login</Text>
</TouchableOpacity>
</View>
</View>
)}
</Formik>
</View>
</KeyboardAvoidingWrapper>
);
};
const onSignUp = ({values}) => {
console.log(values);
}
const MyTextInput = ({label, icon, ...props}) => {
return (
<View style = {styles.inputFieldView}>
<View style = {styles.leftIcon}>
<Octicons name = {icon} size = {30} color = {theme.colors.primary} />
</View>
<Text style = {styles.styledTextInput}>{label}</Text>
<TextInput style = {styles.textInput} {...props} />
</View>
)
}
const styles = StyleSheet.create({
StyledContainer: {
flex: 1,
padding: theme.spacing.m,
paddingTop: theme.spacing.l,
backgroundColor: theme.colors.white,
marginTop: 80,
},
InnerContainer: {
justifyContent: 'center',
alignItems: 'center',
},
PageLogo: {
width: 100,
height: 100,
},
PageTitle: {
...theme.textVariants.h1,
marginTop: theme.spacing.m,
},
TagLine: {
...theme.textVariants.body3,
},
inputFieldView: {
marginTop: 12,
},
styledFormArea: {
justifyContent: 'center',
marginHorizontal: theme.spacing.l,
borderRadius: theme.borderRadius.m,
marginTop: 40,
},
leftIcon: {
position: 'absolute',
zIndex: 1,
marginTop: 28,
marginLeft: 12,
},
styledTextInput: {
...theme.textVariants.body3,
},
textInput: {
backgroundColor: theme.colors.gray,
paddingVertical: 10,
paddingLeft: 50,
paddingRight: theme.spacing.l,
borderRadius: theme.borderRadius.m,
},
loginButton: {
backgroundColor: theme.colors.primary,
alignItems: 'center',
marginTop: 20,
paddingVertical: 8,
borderRadius: theme.borderRadius.m,
},
loginButtonText: {
...theme.textVariants.body2,
color: theme.colors.white,
},
msgBox: {
...theme.textVariants.body3,
alignSelf: 'center',
},
signupLinkView: {
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
padding: theme.spacing.sm,
},
signupText: {
...theme.textVariants.body3,
},
signupLinkButton: {
},
signupLinkText: {
...theme.textVariants.body3,
opacity: 0.6,
},
})
export default SignUp;

很抱歉,如果我的代码写得不太好,也不太有条理。我找不到很多关于firebase身份验证的好教程,所以这是我在看了5个不同的firebase身份认证教程后想到的。哈哈。任何帮助都将不胜感激!

此外,如果你想查看我的整个项目文件,这里是我的github-reo的链接:github-reo-

您应该使用redux或React钩子将用户信息保存到全局状态。

https://reactjs.org/docs/hooks-reference.html#usecontext

https://redux.js.org/introduction/getting-started

在signInWithEmailAndPassword((的回调中返回用户配置文件数据

firebase.auth().signInWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in 
var user = userCredential.user;
/*  user: 
- email
- uid
- displayName
- emailVerified
- phoneNumber
- photoURL
- metadata
...

*/
})
.catch((error) => {
// catch error
});

然后在组件/屏幕中,您可以调用状态来显示用户的数据。

最新更新