Expo 标签导航和堆栈导航

时间:2021-05-03 08:32:55

标签: javascript reactjs react-native expo react-native-tabnavigator

嗨,我想在用户登录时添加标签导航,在用户未登录时添加堆栈导航。所以我写了一个逻辑,但我不知道为什么我会收到错误。请帮帮我。

我只想在用户成功登录时显示标签导航,我使用 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',
    },
  
});

2 个答案:

答案 0 :(得分:1)

我已经创建了一个 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 并在您的 token checking 中执行 App.js 逻辑

您应该做的是,在您的 navigation 所在的位置创建一个名为 App.js 的文件夹。

然后在navigation里面创建两个文件AppNavigator.jsAuthNavigator.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>
  );
}

这是我在所有项目中使用的最有效的身份验证方式..

答案 1 :(得分:0)

显然我必须从我的代码中删除这两个才能正常工作,现在已经解决了。谢谢。

import { StatusBar } from 'expo-status-bar';

<StatusBar style="dark" backgroundColor="black" barStyle="light-content" />