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

React+Firebase项目如何在cookie设置完成后更新authContext及登录状态

问题根因

你遇到的getLoggedIn提前调用问题,本质是createUser函数内部没有正确串联异步流程:外层的await只能等待你显式返回的Promise完成,原有代码里的user.getIdToken()、axios.post都属于嵌套的异步任务,既没有做await处理,也没有将Promise返回给外层,导致await createUser()只等了Firebase创建用户的步骤完成,不等后续接口请求、服务端写入Cookie的流程结束就提前resolve了,自然getLoggedIn会拿不到最新的Cookie。

修复步骤

1. 重写createUser函数,补齐所有异步等待

建议统一用async/await语法,避免混用.then链式调用导致遗漏Promise等待,修改后代码如下:

export const createUser = async (props) => {
  console.log("New User Creation Initiated", props);
  const { email, password } = props;
  try {
    // 等待Firebase创建用户完成
    const { user } = await firebase.auth().createUserWithEmailAndPassword(email, password);
    console.log("createUserWithEmailAndPassword", user);
    // 等待获取用户token完成
    const tokenId = await user.getIdToken();
    const userObject = { tokenId };
    // 关键:等待axios请求完成,服务端返回后Cookie才会写入浏览器
    await axios.post(`${domain}/auth`, userObject);
    return;
  } catch (err) {
    console.log("New User Creation Error: ", err);
    // 抛出错误让外层调用的catch可以捕获到异常
    throw err;
  }
};

2. 优化调用逻辑,统一异步写法

避免await和.then混用,风格更统一也不容易出问题:

const { getLoggedIn, loggedIn } = useContext(AuthContext);

const register = async (e) => {
  e.preventDefault();
  const registerData = {
    email,
    password,
    passwordVerify,
  };
  try {
    await createUser(registerData);
    // 此时createUser所有流程已走完,Cookie已经写入,直接调用校验即可
    await getLoggedIn();
  } catch (err) {
    console.log(err);
  }
};

3. 可选:服务端代码优化(非必须但更稳妥)

原有Express接口里写入用户数据到Firestore的操作没有加等待,可能出现用户数据还没入库就返回的情况,修改后如下:

router.post("/", async (req, res) => {
  console.log("---User signup initiated---");
  try {
    const { tokenId } = req.body;
    console.log("tokenId passed from frontend: ", tokenId);
    const decodedToken = await admin.auth().verifyIdToken(tokenId);
    const { email, uid } = decodedToken;
    console.log("Fetched UID: ", uid);
    console.log("Fetched email: ", email);
    const Users = db.collection("users");
    // 等待用户数据写入完成再往下执行
    await Users.doc(`${uid}`).set({
      email: email,
      posts: [],
    });
    console.log("---jwt signing initiated---");
    const token = jwt.sign(
      {
        user: { email, uid },
      },
      process.env.JWT_SECRET
    );
    console.log("token log: ", token);
    return res
      .cookie("token", token, {
        httpOnly: true,
        sameSite: "none",
        secure: true,
      })
      .send();
  } catch (err) {
    console.log(err);
    return res.sendStatus(500);
  }
});
其他疑问解答
  • 不需要监听Cookie变更:只要异步流程串联正确,createUser返回时Cookie已经写入浏览器,直接调用getLoggedIn即可,监听Cookie属于冗余操作,没有必要。
  • 整体实现思路没有问题:用httpOnly Cookie存JWT是当前比较安全的前端鉴权方案,只要修复异步等待的问题就能正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 08:45:06