React Navigation 在登录时显示不同的选项卡
React Navigation Show Different Tabs On Login
我正在使用带有底部选项卡导航器的反应导航。当应用程序启动时,它会从持久数据存储中获取数据,并根据用户是否登录显示正确的选项卡。但是,一旦用户登录,应用程序必须关闭并重新打开才能显示正确的选项卡。
这是我的 App.js
代码:
import React, { useState } from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";
import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";
import { getGlobalState, setGlobalState } from "./src/GlobalState";
const Tab = createBottomTabNavigator();
export default function App() {
let [fontsLoaded] = useFonts({
Recursive_300,
});
const [isChecking, setIsChecking] = useState(true);
const [isSignedIn, setIsSignedIn] = useState(null);
async function getUserData() {
const username = await SecureStore.getItemAsync("blogger101_Username");
const password = await SecureStore.getItemAsync("blogger101_Password");
const email = await SecureStore.getItemAsync("blogger101_Email");
setGlobalState("username", username);
setGlobalState("password", password);
setGlobalState("email", email);
if (username === null) {
setIsSignedIn(false);
} else {
setIsSignedIn(true);
}
}
if (isChecking) {
return (
<AppLoading
startAsync={getUserData}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
} else {
if (getGlobalState("username") === null && isSignedIn !== false) {
setIsSignedIn(false);
} else if (getGlobalState("username") !== null && isSignedIn !== true) {
setIsSignedIn(true);
}
}
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarButton: [
"Details",
].includes(route.name)
? () => {
return null;
}
: undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<Tab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
{isSignedIn ? (
<Tab.Screen
name="Post_Blog"
component={PostBlog}
options={{
headerLeft: (props) => (
<Entypo name="new-message" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
) : <Tab.Screen
name="Sign_Up"
component={Sign_Up}
options={{
headerLeft: (props) => (
<Feather name="user-plus" size={20} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
}
{isSignedIn ? (
<Tab.Screen name="Logout" component={Logout} />
) : <Tab.Screen
name="Login"
component={Login}
options={{
headerLeft: (props) => (
<SimpleLineIcons name="login" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
}
<Tab.Screen name="Details" component={Blog_Info} />
</Tab.Navigator>
<StatusBar style="dark" />
</NavigationContainer>
);
}
React 导航的 bottomTab 导航器有一个“initialRoute”选项。您可以根据用户是否登录将其设置为不同的路线。
我最终在 Stack Navigator 中 nesting 两个 Tab Navigators。一个选项卡导航器供登录用户使用,另一个供未登录用户使用。
更新后App.js
:
import "react-native-gesture-handler";
import React, { useState } from "react";
import { Text } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createStackNavigator } from '@react-navigation/stack';
import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";
import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";
import { getGlobalState, setGlobalState } from "./src/GlobalState";
const LoggedOutTab = createBottomTabNavigator();
const LoggedInTab = createBottomTabNavigator();
const Stack = createStackNavigator();
function LoggedInTabNavigator() {
return (
<LoggedInTab.Navigator
screenOptions={({ route }) => ({
tabBarButton: route.name === "Details" ? () => null : undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<LoggedInTab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedInTab.Screen
name="Post_Blog"
component={PostBlog}
options={{
headerLeft: (props) => (
<Entypo name="new-message" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedInTab.Screen name="Logout" component={Logout} />
<LoggedInTab.Screen name="Details" component={Blog_Info} />
</LoggedInTab.Navigator>
);
}
function LoggedOutTabNavigator() {
return (
<LoggedOutTab.Navigator
screenOptions={({ route }) => ({
tabBarButton: route.name === "Details" ? () => null : undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<LoggedOutTab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen
name="Sign_Up"
component={Sign_Up}
options={{
headerLeft: (props) => (
<Feather name="user-plus" size={20} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen
name="Login"
component={Login}
options={{
headerLeft: (props) => (
<SimpleLineIcons name="login" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen name="Details" component={Blog_Info} />
</LoggedOutTab.Navigator>
);
}
export default function App() {
let [fontsLoaded] = useFonts({
Recursive_300,
});
const [isChecking, setIsChecking] = useState(true);
const [isSignedIn, setIsSignedIn] = useState(null);
async function getUserData() {
const username = await SecureStore.getItemAsync("blogger101_Username");
const password = await SecureStore.getItemAsync("blogger101_Password");
const email = await SecureStore.getItemAsync("blogger101_Email");
setGlobalState("username", username);
setGlobalState("password", password);
setGlobalState("email", email);
if (username === null) {
setIsSignedIn(false);
} else {
setIsSignedIn(true);
}
}
if (isChecking) {
return (
<AppLoading
startAsync={getUserData}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
} else {
if (getGlobalState("username") === null && isSignedIn !== false) {
setIsSignedIn(false);
} else if (getGlobalState("username") !== null && isSignedIn !== true) {
setIsSignedIn(true);
}
}
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false
}}
initialRouteName={isSignedIn ? "LoggedIn" : "LoggedOut"}
>
<Stack.Screen
name="LoggedIn"
component={LoggedInTabNavigator}
/>
<Stack.Screen
name="LoggedOut"
component={LoggedOutTabNavigator}
/>
</Stack.Navigator>
<StatusBar style="dark" />
</NavigationContainer>
);
}
我正在使用带有底部选项卡导航器的反应导航。当应用程序启动时,它会从持久数据存储中获取数据,并根据用户是否登录显示正确的选项卡。但是,一旦用户登录,应用程序必须关闭并重新打开才能显示正确的选项卡。
这是我的 App.js
代码:
import React, { useState } from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";
import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";
import { getGlobalState, setGlobalState } from "./src/GlobalState";
const Tab = createBottomTabNavigator();
export default function App() {
let [fontsLoaded] = useFonts({
Recursive_300,
});
const [isChecking, setIsChecking] = useState(true);
const [isSignedIn, setIsSignedIn] = useState(null);
async function getUserData() {
const username = await SecureStore.getItemAsync("blogger101_Username");
const password = await SecureStore.getItemAsync("blogger101_Password");
const email = await SecureStore.getItemAsync("blogger101_Email");
setGlobalState("username", username);
setGlobalState("password", password);
setGlobalState("email", email);
if (username === null) {
setIsSignedIn(false);
} else {
setIsSignedIn(true);
}
}
if (isChecking) {
return (
<AppLoading
startAsync={getUserData}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
} else {
if (getGlobalState("username") === null && isSignedIn !== false) {
setIsSignedIn(false);
} else if (getGlobalState("username") !== null && isSignedIn !== true) {
setIsSignedIn(true);
}
}
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarButton: [
"Details",
].includes(route.name)
? () => {
return null;
}
: undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<Tab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
{isSignedIn ? (
<Tab.Screen
name="Post_Blog"
component={PostBlog}
options={{
headerLeft: (props) => (
<Entypo name="new-message" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
) : <Tab.Screen
name="Sign_Up"
component={Sign_Up}
options={{
headerLeft: (props) => (
<Feather name="user-plus" size={20} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
}
{isSignedIn ? (
<Tab.Screen name="Logout" component={Logout} />
) : <Tab.Screen
name="Login"
component={Login}
options={{
headerLeft: (props) => (
<SimpleLineIcons name="login" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
}
<Tab.Screen name="Details" component={Blog_Info} />
</Tab.Navigator>
<StatusBar style="dark" />
</NavigationContainer>
);
}
React 导航的 bottomTab 导航器有一个“initialRoute”选项。您可以根据用户是否登录将其设置为不同的路线。
我最终在 Stack Navigator 中 nesting 两个 Tab Navigators。一个选项卡导航器供登录用户使用,另一个供未登录用户使用。
更新后App.js
:
import "react-native-gesture-handler";
import React, { useState } from "react";
import { Text } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createStackNavigator } from '@react-navigation/stack';
import { SimpleLineIcons, Entypo, Feather } from "@expo/vector-icons";
import { useFonts, Recursive_300 } from "@expo-google-fonts/inter";
import { StatusBar } from "expo-status-bar";
import AppLoading from "expo-app-loading";
import * as SecureStore from "expo-secure-store";
import Blogs from "./src/screens/Blogs";
import Blog_Info from "./src/screens/DetailsScreen";
import Login from "./src/screens/Login";
import Sign_Up from "./src/screens/Sign_up";
import Logout from "./src/screens/Logout";
import PostBlog from "./src/screens/NewBlog";
import { getGlobalState, setGlobalState } from "./src/GlobalState";
const LoggedOutTab = createBottomTabNavigator();
const LoggedInTab = createBottomTabNavigator();
const Stack = createStackNavigator();
function LoggedInTabNavigator() {
return (
<LoggedInTab.Navigator
screenOptions={({ route }) => ({
tabBarButton: route.name === "Details" ? () => null : undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<LoggedInTab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedInTab.Screen
name="Post_Blog"
component={PostBlog}
options={{
headerLeft: (props) => (
<Entypo name="new-message" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedInTab.Screen name="Logout" component={Logout} />
<LoggedInTab.Screen name="Details" component={Blog_Info} />
</LoggedInTab.Navigator>
);
}
function LoggedOutTabNavigator() {
return (
<LoggedOutTab.Navigator
screenOptions={({ route }) => ({
tabBarButton: route.name === "Details" ? () => null : undefined,
tabBarIcon: ({ focused, color, size }) => {
if (route.name === "Blogs") {
return <Entypo name="text-document" size={size} color={color} />;
} else if (route.name === "Post_Blog") {
return <Entypo name="new-message" size={size} color={color} />;
} else if (route.name === "Login") {
return <SimpleLineIcons name="login" size={size} color={color} />;
} else if (route.name === "Sign_Up") {
return <Feather name="user-plus" size={size} color={color} />;
} else if (route.name === "Logout") {
return (
<SimpleLineIcons name="logout" size={size} color={color} />
);
}
},
tabBarActiveTintColor: "tomato",
tabBarInactiveTintColor: "gray",
})}
>
<LoggedOutTab.Screen
name="Blogs"
component={Blogs}
initialParams={{ message: "" }}
options={{
headerLeft: (props) => (
<Entypo name="text-document" size={26} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen
name="Sign_Up"
component={Sign_Up}
options={{
headerLeft: (props) => (
<Feather name="user-plus" size={20} color="black" />
),
headerRight: (props) => (
<Text style={{ fontSize: 16 }}>
<Feather name="user" size={24} color="black" />
User: {getGlobalState("username")}
</Text>
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen
name="Login"
component={Login}
options={{
headerLeft: (props) => (
<SimpleLineIcons name="login" size={26} color="black" />
),
headerLeftContainerStyle: { paddingLeft: 10 },
headerRightContainerStyle: { paddingRight: 10 },
}}
/>
<LoggedOutTab.Screen name="Details" component={Blog_Info} />
</LoggedOutTab.Navigator>
);
}
export default function App() {
let [fontsLoaded] = useFonts({
Recursive_300,
});
const [isChecking, setIsChecking] = useState(true);
const [isSignedIn, setIsSignedIn] = useState(null);
async function getUserData() {
const username = await SecureStore.getItemAsync("blogger101_Username");
const password = await SecureStore.getItemAsync("blogger101_Password");
const email = await SecureStore.getItemAsync("blogger101_Email");
setGlobalState("username", username);
setGlobalState("password", password);
setGlobalState("email", email);
if (username === null) {
setIsSignedIn(false);
} else {
setIsSignedIn(true);
}
}
if (isChecking) {
return (
<AppLoading
startAsync={getUserData}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
} else {
if (getGlobalState("username") === null && isSignedIn !== false) {
setIsSignedIn(false);
} else if (getGlobalState("username") !== null && isSignedIn !== true) {
setIsSignedIn(true);
}
}
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false
}}
initialRouteName={isSignedIn ? "LoggedIn" : "LoggedOut"}
>
<Stack.Screen
name="LoggedIn"
component={LoggedInTabNavigator}
/>
<Stack.Screen
name="LoggedOut"
component={LoggedOutTabNavigator}
/>
</Stack.Navigator>
<StatusBar style="dark" />
</NavigationContainer>
);
}