You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Navigation登录界面未正常显示问题排查求助

问题分析:SecureStore获取Token后导航异常

问题描述

我尝试通过SecureStore获取token来引导用户进入对应界面,但遇到异常:当token为null时,没有显示LoginScreen(而是显示了首页界面);手动给token赋值时,登录界面会直接显示,登录后设置token也能正常跳转至首页。

相关代码

App.js

import * as React from 'react';
import { Pressable } from 'react-native';
import style from './Style';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons, AntDesign, MaterialCommunityIcons } from '@expo/vector-icons';
import HomeScreen from './components/HomeScreen.jsx';
import SigninScreen from './components/SigninScreen.jsx';
import ProfilScreen from './components/ProfilScreen.jsx';
import FormScreen from './components/FormScreen.jsx';
import LoginScreen from './components/LoginScreen.jsx';
import LogoTitle from './components/utils/LogoTitle.jsx';
import * as SplashScreen from 'expo-splash-screen';
import * as SecureStore from 'expo-secure-store';
import { save, getValueFor, deleteValueFor } from './js/secureStore';

SplashScreen.preventAutoHideAsync();

const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();

function BottomTabs({ navigation }) {
  return (
    <Tab.Navigator screenOptions={{ tabBarShowLabel: false }}>
      <Tab.Screen
        name="Home"
        component={HomeScreen}
        options={{
          tabBarIcon: () => (
            <Ionicons name="home" color="black" size={28} />
          ),
          headerTitle: (props) => <LogoTitle {...props} title="FestiZ" size={35} />,
          headerRight: () => (
            <Pressable onPress={() => navigation.navigate('Login')}>
              <MaterialCommunityIcons name="face-man-profile" size={24} color="black" style={style.iconProfil} />
            </Pressable>

          ),
        }}
      />
      <Tab.Screen
        name="Form"
        component={FormScreen}
        options={{
          headerTitle: (props) => <LogoTitle {...props} title="Party" size={35} />,
          tabBarIcon: () => (
            <AntDesign name="pluscircleo" color="black" size={34} />
          ),
        }}
      />
      <Tab.Screen
        name="Party"
        component={SigninScreen}
        options={{
          headerTitle: (props) => <LogoTitle {...props} title="Profil" size={35} />,
          tabBarIcon: () => (
            <MaterialCommunityIcons name="party-popper" size={28} color="black" />
          ),
        }}
      />
    </Tab.Navigator>
  );
}

function HomePack() {
  return (
    <Stack.Navigator options={{ headerShown: false }}>
      <Stack.Screen name="Tabs" component={BottomTabs} options={{ headerShown: false }} />
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen
            name="Profil"
            component={ProfilScreen}
            options={{
              headerTitle: (props) => <LogoTitle {...props} title="Profil" size={25} />,
            }}
          />
    </Stack.Navigator>
  );
}

function App() {
  const [token, onChangeToken] = React.useState(null);
  // save('userToken', 'hiudekzn6764huidb');

  React.useEffect(() => {
    const getTokenAsync = async () => {
      try {
        await SecureStore.getItemAsync('userToken').then((data) => {
          onChangeToken(data);
        });
      } catch (e) {
        console.log(e);
      }
    };

    getTokenAsync();
  }, []);

  return (
    <NavigationContainer>
      <Stack.Navigator>
        {token == null ? (
          <Stack.Screen name="Login" component={LoginScreen} />
        ) : (
          <Stack.Screen name="HomePack" component={HomePack} options={{ headerShown: false }} />
        )}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

secureStore.js

import * as SecureStore from 'expo-secure-store';

export async function save(key, value) {
    await SecureStore.setItemAsync(key, value);
};

export async function getValueFor(key) {
    let result = await SecureStore.getItemAsync(key);
    if (result) {
        return result;
    }              
};

export async function deleteValueFor(key) {
    await SecureStore.deleteItemAsync(key);
};

问题原因推测

  • 启动屏未手动隐藏:你调用了SplashScreen.preventAutoHideAsync()阻止启动屏自动隐藏,但在获取完token更新状态后,没有调用SplashScreen.hideAsync()来隐藏启动屏。这会导致启动屏一直覆盖在界面上方,看起来像是LoginScreen没显示,实际LoginScreen已经渲染了但被挡住。
  • SecureStore残留数据:可能之前测试时存储过token值,没有清理干净,导致SecureStore.getItemAsync('userToken')返回了非null的旧值,所以渲染了HomePack而不是LoginScreen。可以先调用deleteValueFor('userToken')清理数据后再测试。
  • 异步状态更新的延迟感知:初始渲染时token是null,此时会渲染LoginScreen,但SecureStore的异步操作可能在极短时间内完成并更新token。如果旧的token值存在,状态会快速切换到HomePack,让你误以为没显示LoginScreen。可以在useEffect里获取token后,先打印token值确认实际返回结果。

内容的提问来源于stack exchange,提问作者Sally

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:05:58