为什么我的登录和注销功能中状态没有更新?



目前我有一个简单的React Native应用程序,可用于登录和注销。唯一的问题是,为了完成登录或注销(即带我到另一个屏幕(,我必须刷新应用程序

我想知道我的代码中是否有错误,导致用户无法呈现要显示的屏幕。

StackNavigator.js:

import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { HomeScreen, LoginScreen, RegistrationScreen } from "../screens";
import useAuth from "../hooks/useAuth";
const Stack = createStackNavigator();
const StackNavigator = () => {
const { user } = useAuth();
return (
<Stack.Navigator>
{user ? ( // if user is logged in we show the home screen
<Stack.Screen name="Home" component={HomeScreen} />
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
);
};
export default StackNavigator;

useAuth.js:

import React, { createContext, useContext, useEffect, useState } from "react";
import { auth } from "../model/config";
import {
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
} from "firebase/auth";
const AuthContext = createContext({});
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null); //user is initally null
const [loadingInital, setLoadingInital] = useState(true); //loadingInital is initally true
const [loading, setLoading] = useState(false); //loading is initally false
useEffect(() => {
//This hook allows us to remember the user's login status
const unsub = auth.onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser(null);
}
setLoadingInital(false); //after user is fetched, loadingInital is set to false
});
return unsub(); //unsubscribe from the auth listener
}, []);
const onLoginPress = (email, password) => {
setLoading(true); //loading is set to true
//Takes in two arguments, email and password used in LoginScreen class
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.warn("signed in");
console.warn(user);
//Navigate after sign in
// ...
})
.catch((error) => {
//If any error we will catch
const errorCode = error.code;
if (errorCode === "auth/user-not-found") {
console.warn("User not found");
}
if (errorCode === "auth/wrong-password") {
console.warn("Wrong password");
} else {
console.warn(error);
}
});
setLoading(false); //loading is set to false
};
const onRegisterPress = (email, password, confirmPassword) => {
setLoading(true); //loading is set to true
if (password !== confirmPassword) {
alert("Passwords don't match.");
return;
}
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
const user = userCredential.user;
alert("Welcome");
})
.catch((error) => {
alert(error);
});
setLoading(false); //loading is set to false
};
const signOut = () => {
setLoading(true); //loading is set to true
auth.signOut();
console.warn(user);
setLoading(false); //loading is set to false
};
return (
<AuthContext.Provider
value={{ user, onLoginPress, onRegisterPress, signOut, loading }}
>
{!loadingInital && children}
</AuthContext.Provider>
);
};
//if loadingInital is true, we will render nothing ^
export default function useAuth() {
return useContext(AuthContext);
}

登录屏幕:

import React, { useState } from "react";
import { Image, Text, TextInput, TouchableOpacity, View } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import styles from "./styles"; //styles
import FINAL_STYLES from ".././../FINAL_STYLES"; //styles main
import { auth } from "../../model/config";
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
import useAuth from "../../hooks/useAuth";
export default function LoginScreen({ navigation }) {
const { onLoginPress } = useAuth();
const [email, setEmail] = useState(""); //setting as temp state
const [password, setPassword] = useState("");
const onFooterLinkPress = () => {
navigation.navigate("Registration");
};
//Below we return JSX
return (
<View style={styles.container}>
<KeyboardAwareScrollView
style={{ flex: 1, width: "100%" }}
keyboardShouldPersistTaps="always"
>
<Image
style={styles.logo}
source={require("../../../assets/icon.png")}
/>
<TextInput
style={styles.input}
placeholder="E-mail"
placeholderTextColor="#aaaaaa"
onChangeText={(text) => setEmail(text)}
value={email}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholderTextColor="#aaaaaa"
secureTextEntry
placeholder="Password"
onChangeText={(text) => setPassword(text)}
value={password}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TouchableOpacity
style={[styles.button, { backgroundColor: "#9D3BEA" }]} //TODO: change to global styles
onPress={() => onLoginPress(email, password)}
>
<Text style={styles.buttonTitle}>Log in</Text>
</TouchableOpacity>
<View style={styles.footerView}>
<Text style={styles.footerText}>
Don't have an account?{" "}
<Text onPress={onFooterLinkPress} style={styles.footerLink}>
Sign up
</Text>
</Text>
</View>
</KeyboardAwareScrollView>
</View>
);
}

在我登录后立即更新的最佳方式是什么?谢谢:(

您必须重新加载应用程序才能看到更改,因为在onLoginPress中,您在不调用setUser()的情况下更改user状态,而在加载时运行的useEffect中,您做了正确的事情。更改如下。注意,我添加了setUser(userCredential.user)

const onLoginPress = (email, password) => {
setLoading(true);
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
setUser(userCredential.user);
})
.catch((error) => {
const errorCode = error.code;
if (errorCode === "auth/user-not-found") {
console.warn("User not found");
}
if (errorCode === "auth/wrong-password") {
console.warn("Wrong password");
} else {
console.warn(error);
}
})
.finally(() => { // to make sure it runs after the promise has resolved
setLoading(false);
});
};

你在onRegisterPress中也犯了同样的错误,别忘了修复它。最后在signOut中,在auth.signOut()之后调用setUser(null)以确保重置user

最新更新