Expo 选项卡导航和堆栈导航
Expo Tab Navigation and Stack Navigation
您好,我正在尝试在用户登录时添加选项卡导航,在用户未登录时添加堆栈导航。所以我写了一个逻辑,但我不知道为什么会出现错误。请帮助我。
我只想在用户成功登录时显示选项卡导航我正在使用 Nodejs 后端和 Mongodb 作为数据库。
这是我的 AppNavigator 文件。
AppNavigator.js
import React, { useEffect, useState } from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { NavigationContainer } from '@react-navigation/native';
import SignUp from "../screens/SignupScreen";
import LoginScreen from "../screens/LoginScreen";
import LoadingScreen from "../screens/LoadingScreen";
import HomeScreen from "../screens/HomeScreen";
import AsyncStorage from '@react-native-async-storage/async-storage';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator()
const [isLoggedin, setLogged] = useState(null)
const TabNavigator = () => {
return <TabNavigator>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</TabNavigator>
}
const AuthNavigator = () => {
return (
<Stack.Navigator
headerMode="none"
screenOptions={{
headerStyle: { elevation: 0 },
cardStyle: { backgroundColor: '#fff' }
}}
>
<Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen>
<Stack.Screen name="home" component={HomeScreen}></Stack.Screen>
<Stack.Screen name="login" component={LoginScreen}></Stack.Screen>
<Stack.Screen name="signup" component={SignUp}></Stack.Screen>
</Stack.Navigator>
)
};
const Navigation = () => {
const [user, setUser] = useState('');
useEffect(() => {
if (isLoggedin) {
setUser(userExist)
}
else {
setUser('')
}
}, [])
return (
<NavigationContainer >
{user ? <TabNavigator /> : <AuthNavigator />}
</NavigationContainer>
)
};
function AppNavigator() {
useEffect(() => {
const token = AsyncStorage.getItem('token')
if (token) {
setLogged(true)
}
else {
setLogged(false)
}
}, [])
return (
<Navigation />
);
}
export default AppNavigator;
这是我的 App.js 文件
App.js
import React,{useEffect,useState} from "react";
import { NavigationContainer } from "@react-navigation/native";
import AppNavigator from "./navigation/AppNavigator";
export default function App() {
return (
<AppNavigator />
);
}
我有自己的 LoadingScreen 文件
LoadingScreen.js
import { StatusBar } from 'expo-status-bar';
import React,{useEffect,useState} from 'react';
import { StyleSheet, ActivityIndicator, Image,View,Text } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Button, TextInput } from 'react-native-paper';
// <View style={styles.container}>
export default function LoadingScreen(props) {
const detectLogin = () =>{
const token = AsyncStorage.getItem('token')
if (token) {
props.navigation.navigate("profile")
}
else {
props.navigation.navigate("login")
}
}
useEffect(() => {
detectLogin()
}, [])
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="black">
</ActivityIndicator>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
我创建了一个 Snack 供您查看工作示例
我注意到的第一件事是在你的 TabNavigator
函数中你写了
return <TabNavigator>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</TabNavigator>
相反,你必须写这样的东西
return <Tab.Navigator> // Notice the . here
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</Tab.Navigator>
我猜你的令牌恢复逻辑效率不高。
我建议你制作两个不同的 Navigators
并在你的 App.js
中执行 token checking
逻辑
您应该做的是,在 App.js
所在的位置创建一个名为 navigation
的文件夹。
然后在navigation
里面创建两个文件AppNavigator.js
和AuthNavigator.js
你的 AppNavigator.js
应该是这样的 -
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from '../screens/HomeScreen';
import AccountScreen from '../screens/AccountScreen';
const Tab = createBottomTabNavigator();
function AppNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Accounts" component={AccountScreen} />
</Tab.Navigator>
);
}
export default AppNavigator;
你的 AuthNavigator.js
应该是这样的 -
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import LoadingScreen from '../screens/LoadingScreen';
import HomeScreen from '../screens/HomeScreen';
import LoginScreen from '../screens/LoginScreen';
import SignUp from '../screens/SignUpScreen';
const Stack = createStackNavigator();
function AuthNavigator() {
return (
<Stack.Navigator
headerMode="none"
screenOptions={{
headerStyle: { elevation: 0 },
cardStyle: { backgroundColor: '#fff' },
}}>
<Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen>
<Stack.Screen name="home" component={HomeScreen}></Stack.Screen>
<Stack.Screen name="login" component={LoginScreen}></Stack.Screen>
<Stack.Screen name="signup" component={SignUp}></Stack.Screen>
</Stack.Navigator>
);
}
export default AuthNavigator;
那么你应该从 here
安装 expo-app-loading
然后在你的 App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AppLoading from 'expo-app-loading';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AppNavigator from './navigation/AppNavigator';
import AuthNavigator from './navigation/AuthNavigator';
export default function App() {
const [user, setUser] = useState('');
const [IsReady, setIsReady] = useState(false);
const RestoreUser = async () => {
const token = await AsyncStorage.getItem('token');
if (token) {
setUser(true);
} else {
setUser(false);
}
};
if (!IsReady) {
return (
<AppLoading
startAsync={RestoreUser}
onFinish={() => setIsReady(true)}
onError={() => {}}
/>
);
}
return (
<NavigationContainer>
{user ? <AppNavigator /> : <AuthNavigator />}
</NavigationContainer>
);
}
这是我在所有项目中使用的最有效的身份验证方式..
显然我必须从我的代码中删除这两个才能正常工作,现在已经解决了。谢谢。
import { StatusBar } from 'expo-status-bar';
<StatusBar style="dark" backgroundColor="black" barStyle="light-content" />
您好,我正在尝试在用户登录时添加选项卡导航,在用户未登录时添加堆栈导航。所以我写了一个逻辑,但我不知道为什么会出现错误。请帮助我。
我只想在用户成功登录时显示选项卡导航我正在使用 Nodejs 后端和 Mongodb 作为数据库。
这是我的 AppNavigator 文件。
AppNavigator.js
import React, { useEffect, useState } from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { NavigationContainer } from '@react-navigation/native';
import SignUp from "../screens/SignupScreen";
import LoginScreen from "../screens/LoginScreen";
import LoadingScreen from "../screens/LoadingScreen";
import HomeScreen from "../screens/HomeScreen";
import AsyncStorage from '@react-native-async-storage/async-storage';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator()
const [isLoggedin, setLogged] = useState(null)
const TabNavigator = () => {
return <TabNavigator>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</TabNavigator>
}
const AuthNavigator = () => {
return (
<Stack.Navigator
headerMode="none"
screenOptions={{
headerStyle: { elevation: 0 },
cardStyle: { backgroundColor: '#fff' }
}}
>
<Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen>
<Stack.Screen name="home" component={HomeScreen}></Stack.Screen>
<Stack.Screen name="login" component={LoginScreen}></Stack.Screen>
<Stack.Screen name="signup" component={SignUp}></Stack.Screen>
</Stack.Navigator>
)
};
const Navigation = () => {
const [user, setUser] = useState('');
useEffect(() => {
if (isLoggedin) {
setUser(userExist)
}
else {
setUser('')
}
}, [])
return (
<NavigationContainer >
{user ? <TabNavigator /> : <AuthNavigator />}
</NavigationContainer>
)
};
function AppNavigator() {
useEffect(() => {
const token = AsyncStorage.getItem('token')
if (token) {
setLogged(true)
}
else {
setLogged(false)
}
}, [])
return (
<Navigation />
);
}
export default AppNavigator;
这是我的 App.js 文件
App.js
import React,{useEffect,useState} from "react";
import { NavigationContainer } from "@react-navigation/native";
import AppNavigator from "./navigation/AppNavigator";
export default function App() {
return (
<AppNavigator />
);
}
我有自己的 LoadingScreen 文件
LoadingScreen.js
import { StatusBar } from 'expo-status-bar';
import React,{useEffect,useState} from 'react';
import { StyleSheet, ActivityIndicator, Image,View,Text } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Button, TextInput } from 'react-native-paper';
// <View style={styles.container}>
export default function LoadingScreen(props) {
const detectLogin = () =>{
const token = AsyncStorage.getItem('token')
if (token) {
props.navigation.navigate("profile")
}
else {
props.navigation.navigate("login")
}
}
useEffect(() => {
detectLogin()
}, [])
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="black">
</ActivityIndicator>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
我创建了一个 Snack 供您查看工作示例
我注意到的第一件事是在你的 TabNavigator
函数中你写了
return <TabNavigator>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</TabNavigator>
相反,你必须写这样的东西
return <Tab.Navigator> // Notice the . here
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</Tab.Navigator>
我猜你的令牌恢复逻辑效率不高。
我建议你制作两个不同的 Navigators
并在你的 App.js
token checking
逻辑
您应该做的是,在 App.js
所在的位置创建一个名为 navigation
的文件夹。
然后在navigation
里面创建两个文件AppNavigator.js
和AuthNavigator.js
你的 AppNavigator.js
应该是这样的 -
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from '../screens/HomeScreen';
import AccountScreen from '../screens/AccountScreen';
const Tab = createBottomTabNavigator();
function AppNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Accounts" component={AccountScreen} />
</Tab.Navigator>
);
}
export default AppNavigator;
你的 AuthNavigator.js
应该是这样的 -
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import LoadingScreen from '../screens/LoadingScreen';
import HomeScreen from '../screens/HomeScreen';
import LoginScreen from '../screens/LoginScreen';
import SignUp from '../screens/SignUpScreen';
const Stack = createStackNavigator();
function AuthNavigator() {
return (
<Stack.Navigator
headerMode="none"
screenOptions={{
headerStyle: { elevation: 0 },
cardStyle: { backgroundColor: '#fff' },
}}>
<Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen>
<Stack.Screen name="home" component={HomeScreen}></Stack.Screen>
<Stack.Screen name="login" component={LoginScreen}></Stack.Screen>
<Stack.Screen name="signup" component={SignUp}></Stack.Screen>
</Stack.Navigator>
);
}
export default AuthNavigator;
那么你应该从 here
安装expo-app-loading
然后在你的 App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AppLoading from 'expo-app-loading';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AppNavigator from './navigation/AppNavigator';
import AuthNavigator from './navigation/AuthNavigator';
export default function App() {
const [user, setUser] = useState('');
const [IsReady, setIsReady] = useState(false);
const RestoreUser = async () => {
const token = await AsyncStorage.getItem('token');
if (token) {
setUser(true);
} else {
setUser(false);
}
};
if (!IsReady) {
return (
<AppLoading
startAsync={RestoreUser}
onFinish={() => setIsReady(true)}
onError={() => {}}
/>
);
}
return (
<NavigationContainer>
{user ? <AppNavigator /> : <AuthNavigator />}
</NavigationContainer>
);
}
这是我在所有项目中使用的最有效的身份验证方式..
显然我必须从我的代码中删除这两个才能正常工作,现在已经解决了。谢谢。
import { StatusBar } from 'expo-status-bar';
<StatusBar style="dark" backgroundColor="black" barStyle="light-content" />