我是 React Native 的新手,在尝试获取用户令牌以检查用户是否经过身份验证时遇到问题。如果找到令牌,我认为用户已通过身份验证并尝试显示根堆栈。然而,我遇到的问题是 AuthStack 的屏幕仍然安装在 RootStack 的顶部。有人可以帮助我吗
下面是我的代码:
import { router, Slot, Stack, Tabs } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { useContext, useEffect, useState } from "react";
import { AuthContext, AuthContextProvider } from "../context/AuthContext";
import { ActivityIndicator, View } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { getUserInforWithToken } from "../controller/AuthController";
function RootStack() {
return (
<Stack>
<Stack.Screen name="(root)/index" options={{ title: "Welcome" }} />
</Stack>
);
}
function AuthStack() {
return (
<Stack
screenOptions={{
headerStyle: { backgroundColor: "#6779ef" },
headerTintColor: "white",
contentStyle: { backgroundColor: "#6779ef" },
headerShown: false,
}}>
<Stack.Screen name="(auth)/index" options={{ title: "Login Page" }} />
<Stack.Screen name="(auth)/signup" options={{ title: "Sign Up Page" }} />
</Stack>
);
}
function Root() {
const { setIsLogin, setToken, setIsTryingLogin, isTryingLogin } =
useContext(AuthContext);
const [isLoading, setIsLoading] = useState(true);
const { isLogin } = useContext(AuthContext);
useEffect(() => {
const checkAuth = async () => {
const token = await AsyncStorage.getItem("token");
if (token) {
console.log("token found, user logged in");
setIsLogin(true);
setToken(token);
} else {
setIsLogin(false);
}
// Set trying login to false after we check for token
setIsTryingLogin(false);
};
checkAuth();
}, []); // This runs only once on component mount
useEffect(() => {
if (!isTryingLogin) {
setIsLoading(false);
}
}, [isTryingLogin]);
if (isLoading) {
console.log("Loading...");
return (
<View className="flex-1 justify-center items-center">
<ActivityIndicator className="p-2 m-2" animating size="large" />
</View>
);
}
return isLogin ? <RootStack /> : <AuthStack />;
}
export default function Layout() {
return (
<AuthContextProvider>
<StatusBar style="light" />
<Root />
</AuthContextProvider>
);
}
我尝试了 Chatgpt 并尝试阅读文档,甚至尝试关注某人的 YouTube 频道并指出有效
您遇到的问题可能是由于在当前设置中同时安装了两个堆栈(RootStack 和 AuthStack)。
不是有条件地渲染两个堆栈 在根堆栈中,而是根据 isLogin 状态有条件地在堆栈导航器本身中渲染正确的堆栈。
例如。
import { router, Slot, Stack, Tabs } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { useContext, useEffect, useState } from "react";
import { AuthContext, AuthContextProvider } from "../context/AuthContext";
import { ActivityIndicator, View } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
function Root() {
const { setIsLogin, setToken, setIsTryingLogin, isTryingLogin, isLogin } =
useContext(AuthContext);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const checkAuth = async () => {
const token = await AsyncStorage.getItem("token");
if (token) {
console.log("token found, user logged in");
setIsLogin(true);
setToken(token);
} else {
setIsLogin(false);
}
// Set trying login to false after we check for token
setIsTryingLogin(false);
};
checkAuth();
}, []); // This runs only once on component mount
useEffect(() => {
if (!isTryingLogin) {
setIsLoading(false);
}
}, [isTryingLogin]);
if (isLoading) {
console.log("Loading...");
return (
<View className="flex-1 justify-center items-center">
<ActivityIndicator className="p-2 m-2" animating size="large" />
</View>
);
}
return (
<Stack
screenOptions={{
headerShown: false, // Hides header for all screens by default
}}
>
{isLogin ? (
<>
{/* Root Stack for authenticated users */}
<Stack.Screen
name="(root)/index"
component={RootStack}
options={{ title: "Welcome" }}
/>
</>
) : (
<>
{/* Auth Stack for unauthenticated users */}
<Stack.Screen
name="(auth)/index"
component={AuthStack}
options={{ title: "Login Page" }}
/>
<Stack.Screen
name="(auth)/signup"
component={AuthStack}
options={{ title: "Sign Up Page" }}
/>
</>
)}
</Stack>
);
}
function RootStack() {
return (
<Stack>
<Stack.Screen name="(root)/index" options={{ title: "Welcome" }} />
</Stack>
);
}
function AuthStack() {
return (
<Stack
screenOptions={{
headerStyle: { backgroundColor: "#6779ef" },
headerTintColor: "white",
contentStyle: { backgroundColor: "#6779ef" },
headerShown: false,
}}
>
<Stack.Screen name="(auth)/index" options={{ title: "Login Page" }} />
<Stack.Screen name="(auth)/signup" options={{ title: "Sign Up Page" }} />
</Stack>
);
}
export default function Layout() {
return (
<AuthContextProvider>
<StatusBar style="light" />
<Root />
</AuthContextProvider>
);
}