这可能是一个愚蠢的问题,但我一直在关注一些关于如何使用 Firebase 制作登录屏幕的 react native / expo 教程。我遵循的教程还制作了一个加载屏幕(使用加载状态),它将在 Firebase 连接时显示。不幸的是,加载状态对我来说永远不会结束,我不知道如何修复它。
这是我的 Navigator.js 文件:
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>
)
}
这是我的 Home.js 文件:
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;
这是 Login.js 文件:
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;
最后,Signup.js 文件:
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;