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

React中如何在Firebase验证用户有效性后再发送POST请求

Firebase Auth状态未就绪时发送请求的解决方案

问题说明

当前通过以下代码获取Firebase用户的idToken并携带到后端请求:

const user = firebase.auth().currentUser
const idToken = await user.getIdToken()

请求发送代码:

var res = await axios.post(backUrl + "account/load_balance", { 
uid: uid, 
id: id 
},
{
  headers: {
  Authorization: 'Bearer ' + idToken
   }});

多数场景下代码正常,但在特定页面中,请求会在user仍为null、idToken未生成时就发送到服务器。已知可以通过onAuthStateChanged方法监听用户状态,等待用户信息就绪后再触发逻辑,但不清楚如何集成到现有代码中。

现有代码问题

原组件中,useEffect仅依赖uid是否存在就调用loadBlockchainData,但Firebase的currentUser初始化是异步的——即使本地存储有uid,Firebase可能还未完成用户状态的同步,此时firebase.auth().currentUser会返回null,导致后续获取idToken失败。

集成onAuthStateChanged的方案

通过onAuthStateChanged监听用户登录状态,只有当确认用户已登录(user对象存在)时,再执行后端请求逻辑。同时要在组件卸载时移除监听,避免内存泄漏。

修改后的完整代码

const RoutingForPortfolio = (props) => {
    let uid = localStorage.getItem("account-info");
    let { id } = useParams();

    const loadBlockchainData = async (dispatch, user) => {
        if (id === null || id === undefined) {
            id = "test";
        }
        
        // 直接使用监听回调传入的user对象,确保已就绪
        const idToken = await user.getIdToken()
        console.log(idToken)
        var res = await axios.post(backUrl + "account/load_balance", { 
        uid: uid, 
        id: id 
        },
        {
          headers: {
          Authorization: 'Bearer ' + idToken
           }});
        if (res.data === null) {
            await wait(2);
            document.location.href = "/logout"
            return;
        }
        else {
            const account = res.data.address;
            dispatch(web3AccountLoaded(account));
            localStorage.setItem("account-address", account);
            if (res.data.token_flag && res.data.exchange_flag) {
                await dispatch(setLoginUserName(res.data.name));
                await dispatch(setLoginUserEmail(res.data.email));
                if (res.data.balance !== null) {
                    await dispatch(etherBalanceLoaded(res.data.balance[0]));
                    await dispatch(tokenBalanceLoaded(res.data.balance[1]));
                    await dispatch(exchangeEtherBalanceLoaded(res.data.balance[2]));
                    await dispatch(exchangeTokenBalanceLoaded(res.data.balance[3]));
                }
            }
            else {
                Swal.fire({
                    icon: "error",
                    title: "Error...",
                    text: "Error 485 - Please report to admin",
                });
                return;
            }
        }
    };

    useEffect(() => {
        // 注册用户状态监听
        const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
            // 仅当用户已登录且本地uid存在时,执行数据加载
            if (user && uid) {
                loadBlockchainData(props.dispatch, user);
            } else if (!user && uid) {
                // 本地有uid但用户未登录,跳转到登录页
                document.location.href = "/logout";
            }
        });

        // 组件卸载时移除监听
        return () => unsubscribe();
    }, [props.dispatch, uid]);

    return (
        <>
            {uid ? (
                <div>
                    <Portfolio id={id} />
                </div>
            ) : (
                <Login />
            )}
        </>
    );
};

关键修改点

  • 将loadBlockchainData改为接收user参数,确保使用的是已就绪的用户对象
  • 在useEffect中注册onAuthStateChanged监听,只有当user存在且本地uid有效时,才调用数据加载逻辑
  • 添加监听的清理函数,组件卸载时取消监听,避免内存泄漏
  • 增加了本地有uid但用户未登录的处理,直接跳转登出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:50:29