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

React Native使用SecureStore检测用户登录状态异常问题排查

问题分析与修复方案

核心问题

  1. IsAuth是异步函数,直接调用返回Promise对象(你看到的{"_A": null, "_x": 0, "_y": 0, "_z": null}就是Promise的内部结构),而非预期的布尔值,导致x永远为真(因为对象非空)。
  2. UseToken中直接将异步函数getToken()传给useState,导致token状态初始值是Promise,不是实际的token字符串或null,后续传给IsAuth时会引发解析错误。

修复代码

1. 修正UseToken.js:异步初始化token状态

import { useState, useEffect } from 'react';
import * as SecureStore from 'expo-secure-store';

export default function UseToken() {
    const [token, setToken] = useState(null);

    // 异步获取token并更新状态
    useEffect(() => {
        const fetchToken = async () => {
            const tokenString = await SecureStore.getItemAsync("iScore");
            // 解析存储的JSON字符串,避免双重序列化
            const parsedToken = tokenString ? JSON.parse(tokenString) : null;
            setToken(parsedToken);
        };
        fetchToken();
    }, []);

    const saveToken = async userToken => {
        await SecureStore.setItemAsync("iScore", JSON.stringify(userToken));
        setToken(userToken);
    };

    return {
        setToken: saveToken,
        token
    };
}

2. 修正Login.js:正确处理异步认证逻辑

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import UseToken from './UseToken';
import IsAuth from './IsAuth';

export default function Login() {
    const { token } = UseToken();
    const navigate = useNavigate();
    const [isAuthenticated, setIsAuthenticated] = useState(false);
    const [isLoading, setIsLoading] = useState(true); // 加载状态避免误导航

    useEffect(() => {
        const checkAuth = async () => {
            if (!token) {
                setIsAuthenticated(false);
                setIsLoading(false);
                return;
            }
            const authResult = await IsAuth(token);
            setIsAuthenticated(authResult);
            setIsLoading(false);
        };
        checkAuth();
    }, [token]);

    // 认证状态确定后再执行导航
    useEffect(() => {
        if (!isLoading && isAuthenticated) {
            navigate("/countries");
        }
    }, [navigate, isAuthenticated, isLoading]);

    // 加载中显示占位内容
    if (isLoading) {
        return <div>Loading...</div>;
    }

    return (
        // 你的登录表单代码
        <div>Login Page</div>
    );
}

3. 优化IsAuth.js:调整判断顺序避免冗余错误

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

export default async function IsAuth(token) {
    // 先判断token是否存在
    if (!token) {
        await SecureStore.deleteItemAsync("iScore");
        return false;
    }

    try {
        const decoded = jwt.decode(token);
        if (!decoded?.exp) {
            await SecureStore.deleteItemAsync("iScore");
            return false;
        }
        // 检查token是否过期
        if (Math.round(Date.now() / 1000) >= decoded.exp) {
            await SecureStore.deleteItemAsync("iScore");
            return false;
        }
        return true;
    } catch (e) {
        await SecureStore.deleteItemAsync("iScore");
        return false;
    }
}

关键说明

  • 异步操作必须配合useEffect和状态更新,不能直接将Promise赋值给变量或状态初始值。
  • 增加isLoading状态可以避免在认证结果出来前执行导航逻辑,提升用户体验。
  • 注意JSON序列化/解析的一致性,避免双重序列化导致token解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:16:00