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

React Native Expo登录后StackNavigator首页不更新问题求助

问题分析与解决方案

核心问题

  1. 状态不共享:StackNavigator组件内维护了独立的isLoggedIn局部状态,和AuthContext中的登录状态完全脱节。登录成功后AuthContext更新了状态,但StackNavigator的局部状态没有同步,导致导航器不会重新渲染切换页面。
  2. AuthContext方法错误:login方法里的await isLoggedIn(true);是错误调用——isLoggedIn是状态变量,不是设置状态的函数,正确操作应该是调用Context中定义的状态更新方法(比如setIsLoggedIn)。
  3. 初始化后未监听状态变化:StackNavigator仅在组件挂载时通过useEffect检查一次登录状态,后续登录状态变更不会触发导航器重新渲染。

修正步骤

1. 修复AuthContext的login方法

确保调用正确的状态更新函数,移除不必要的await(状态更新为同步操作):

const login = async (email, password) => {
  setIsLoading(true);
  try {
    const response = await axios.post('https://ecommerce.comercializadoramya.com/api/v1/login', {
      email,
      password,
      device_name: 'Mobile'
    });

    if(response.data.success){
      const token = response.data.token;
      const user_info = response.data.user;

      await AsyncStorage.setItem('token', token);
      await AsyncStorage.setItem('user_info', JSON.stringify(user_info));

      setUserInfo(user_info);
      // 调用Context中定义的setIsLoggedIn方法更新全局登录状态
      setIsLoggedIn(true);
    }else{
      setErrorMessage(response.data.message);
    } 
  } catch (error) {
    if (error.response?.status === 401) {
      setErrorMessage('La contraseña es incorrecta por favor intenta nuevamente');
    } else if (error.response?.status === 404) {
      setErrorMessage('No existe un usuario con este correo electrónico');
    } else {
      setErrorMessage('Ha ocurrido un error. Intenta nuevamente.');
    }
  }
  setIsLoading(false);
};

2. 让StackNavigator依赖AuthContext的全局状态

移除StackNavigator内的局部isLoggedIn和相关useEffect,直接从AuthContext中获取登录状态:

const Stack = createStackNavigator();

const StackNavigator = () => {
  // 通过自定义Hook获取AuthContext中的全局状态
  const { isLoggedIn, isLoading } = useAuth();

  return (
    <Stack.Navigator>
      {isLoggedIn ? (
        <>
          <Stack.Screen name="Inicio" component={BottomTabNavigator} options={{headerShown: false}}/>
          <Stack.Screen name="Order" component={OrderScreen} 
            options={{ title: 'Realiza tu pedido' }}
          />
          <Stack.Screen name="Detalle" component={ProductDetailScreen} 
            options={{ title: 'Información del producto' }}
          />
          <Stack.Screen name="Home" component={HomeSreen} />
          <Stack.Screen name="Orders" component={OrderDetailScreen} 
            options={{ title: 'Historial de pedidos' }}
          />
          <Stack.Screen name="DatosFacturacion" component={InvoiceDataScreen} 
            options={{ title: 'Datos de facturación' }}
          />
          <Stack.Screen name="ProductosPorCategoria" component={ShowPerCategoryListScreen} 
            options={{ title: 'Productos por categoria' }}
          />
          <Stack.Screen name="Confirmation" component={ConfirmationOrderScreen} 
            options={{headerShown: false}}
          />
        </>
      ) : (
        <>
          <Stack.Screen name="Login" component={LoginScreen} />
        </>
      )}
    </Stack.Navigator>
  );
}

export default StackNavigator;

3. 完善AuthContext的初始化逻辑

在AuthContext的Provider中统一处理登录状态初始化,确保全局状态正确:

// 示例AuthContext完整结构
import { createContext, useContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userInfo, setUserInfo] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  useEffect(() => {
    const checkLoginStatus = async () => {
      try {
        const token = await AsyncStorage.getItem("token");
        if (token) {
          const storedUserInfo = await AsyncStorage.getItem("user_info");
          setUserInfo(storedUserInfo ? JSON.parse(storedUserInfo) : null);
          setIsLoggedIn(true);
          // 可选:登录状态验证后刷新应用数据
          // await doAsyncRefresh();
        }
      } catch (err) {
        setIsLoggedIn(false);
      }
    };
    checkLoginStatus();
  }, []);

  const login = async (email, password) => {
    // 放入修正后的login方法
  };

  return (
    <AuthContext.Provider value={{ isLoggedIn, userInfo, isLoading, errorMessage, login, setIsLoggedIn }}>
      {children}
    </AuthContext.Provider>
  );
};

// 自定义Hook简化Context调用
export const useAuth = () => useContext(AuthContext);

额外注意事项

  • 确保App根组件被AuthProvider包裹,让所有子组件都能访问全局登录状态。
  • 登录成功后无需手动跳转页面,isLoggedIn状态更新后,StackNavigator会自动重新渲染并切换到已登录路由组。
  • 移除所有局部登录状态,避免状态冗余和不同步问题。

内容的提问来源于stack exchange,提问作者Sebastian Henao Cardona

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:05:56