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

React Native集成Laravel Sanctum时AsyncStorage无法持久化问题

React Native + Laravel Sanctum 认证问题修复方案

问题概述

在React Native应用中使用Laravel Sanctum API实现用户认证时,遇到以下问题:

  • 登录时useState的userInfo数据正确,但AsyncStorage存储的userInfo异常;
  • 重启应用后自动回到登录页,无法保持登录状态;
  • 调用登出API时返回401未授权错误。

错误分析与修复步骤

一、AsyncStorage存储userInfo异常修复

错误原因:setUserInfo是异步状态更新操作,登录时直接用userInfo存储到AsyncStorage,此时userInfo还是初始的空数组/空值,导致存储数据异常。

修复代码:直接使用API返回的res.data进行存储:

// AuthContext.js 中login函数的修复片段
if (res.data.status === 200) {
    console.log(res.data)
    setUserInfo(res.data)
    // 用res.data替代未更新的userInfo状态
    AsyncStorage.setItem("userInfo", JSON.stringify(res.data));
    AsyncStorage.setItem("auth_token", res.data.token);
    AsyncStorage.setItem("auth_name", res.data.username);
    setIsLoading(false)
}

二、重启应用无法保持登录修复

错误原因:应用重启时,AuthProvider的userInfo初始化为空值,未从AsyncStorage读取之前保存的用户数据,导致路由判断为未登录。

修复代码:在AuthProvider中添加useEffect,组件挂载时加载保存的用户信息:

// AuthContext.js 中添加以下代码
import { useEffect } from 'react';

export const AuthProvider = ({children}) => {
    // 初始化userInfo为null更合理,替代原数组初始化
    const [userInfo, setUserInfo] = useState(null)
    const [isLoading, setIsLoading] = useState(false)

    // 加载本地保存的用户信息
    useEffect(() => {
        const loadSavedUser = async () => {
            try {
                const savedUser = await AsyncStorage.getItem("userInfo");
                const savedToken = await AsyncStorage.getItem("auth_token");
                if (savedUser && savedToken) {
                    setUserInfo(JSON.parse(savedUser));
                }
            } catch (error) {
                console.error("加载用户信息失败:", error);
            }
        };
        loadSavedUser();
    }, []);

    // 原login、logout等逻辑保持(后续修复logout)
}

三、Navigation中AsyncStorage使用错误修复

错误原因:AsyncStorage.getItem是异步函数,直接调用会返回Promise对象,无法直接用于路由判断;且路由判断应依赖context中的userInfo,无需直接读取AsyncStorage。

修复代码:

// Navigation.js 修复后
const Stack = createNativeStackNavigator();
const Navigation = () => {
  const { userInfo } = useContext(AuthContext);

  return (
    <NavigationContainer>
      // 使用可选链操作符处理userInfo为null的情况
      {userInfo?.username ? <AppStack /> : <AuthStack />}
    </NavigationContainer>
  );
};

四、登出401错误修复

1. Axios拦截器异步获取token错误

错误原因:AsyncStorage.getItem是异步函数,直接赋值会把Promise对象作为token,导致请求头Authorization无效,后端无法识别认证信息。

修复代码:

// App.js 中Axios拦截器修复
axios.interceptors.request.use(async function (config) {
    const token = await AsyncStorage.getItem("auth_token");
    config.headers.Authorization = token ? `Bearer ${token}` : "";
    return config;
});

2. 登出逻辑不完整

错误原因:登出时未清除所有用户相关存储项,且原代码未使用async/await处理异步操作。

修复代码:

// AuthContext.js 中logout函数修复
const logout = async () => {
    setIsLoading(true)
    try {
        const res = await axios.post("/api/logout");
        if (res.data.status === 200) {
            console.log(res.data)
            // 批量清除所有相关存储项
            await AsyncStorage.multiRemove(["userInfo", "auth_token", "auth_name"]);
            setUserInfo(null);
        }
    } catch (e) {
        console.log(e)
    } finally {
        setIsLoading(false)
    }
};

3. Laravel登出路由未添加认证中间件

错误原因:未给logout路由添加auth:sanctum中间件,导致后端无法识别登录用户,返回401。

修复代码:

// routes/api.php
Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');

完整认证流程

  1. 登录:

    • 获取CSRF Cookie;
    • 发送登录请求,验证成功后获取用户信息与token;
    • 将用户信息、token存入AsyncStorage;
    • 更新context状态,路由自动切换至仪表盘。
  2. 应用重启:

    • AuthProvider挂载时读取AsyncStorage中的用户数据;
    • 更新userInfo状态,路由判断为已登录,直接进入仪表盘。
  3. 登出:

    • 调用Laravel登出API,后端清除用户所有token;
    • 清除AsyncStorage中所有用户相关数据;
    • 重置userInfo状态,路由切换至登录页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:10:25