使用Firebase Auth与Redux时displayName无法更新的问题求助
解决Firebase Auth注册时displayName未同步的问题
你的推测完全正确——onAuthStateChanged会在createUserWithEmailAndPassword成功后立刻触发,而updateProfile是异步操作,这时候用户对象还没完成displayName的更新,导致你拿到的user里displayName还是null,后续写入数据库自然也没有这个字段。下面是具体的修复步骤:
1. 确保注册时updateProfile完成后再处理后续逻辑
修改你的registerUser函数,使用await等待updateProfile完成,彻底避免异步竞态问题:
export const registerUser = (value) => { const { firstName, surname, email, password } = value; return async (dispatch) => { try { const result = await firebaseAuth.createUserWithEmailAndPassword(email, password); const user = result.user; // 等待displayName更新完成,再继续后续操作 await user.updateProfile({ displayName: `${firstName} ${surname}`, }); // 手动触发用户文档同步,不用被动等onAuthChanged await createUserProfileDocument(user); // 这里可以dispatch登录成功的action,比如dispatch(loginSuccess(user)) } catch (error) { console.log("Unable to create user profile: ", error); // 这里可以dispatch登录失败的action,提示用户注册出错 } }; };
2. 优化createUserProfileDocument函数
原函数用once回调的方式,无法正确等待写入完成,而且只在uid不存在时写入,后续用户更新displayName也不会同步到数据库。改成基于Promise的写法,同时支持同步最新用户信息:
export const createUserProfileDocument = async (user) => { if (!user) return; const { uid, displayName, email } = user; const userReference = database.ref(`users/${uid}`); // 获取用户文档快照,判断是否存在 const snapshot = await userReference.get(); if (!snapshot.exists()) { // 不存在则创建新文档,写入基础信息 await userReference.set({ displayName, email, createdAt: new Date().toISOString() // 可选:添加创建时间戳 }); } else { // 文档已存在时,同步最新的displayName和email(按需调整) await userReference.update({ displayName, email }); } return userReference; };
3. 调整persistedSession的监听逻辑
onAuthStateChanged可能在用户信息未完全更新时触发,所以可以在监听里强制刷新用户信息,确保拿到最新的displayName:
export const persistedSession = () => { return async (dispatch) => { dispatch(requestLogin()); firebaseAuth.onAuthStateChanged(async (user) => { if (user) { // 从Firebase服务器拉取最新用户信息,避免拿到缓存的旧数据 await user.reload(); const freshUser = firebaseAuth.currentUser; // 同步最新信息到数据库 const userRef = await createUserProfileDocument(freshUser); // 监听用户文档变化,更新Redux状态 userRef.on("value", (snapshot) => { const data = snapshot.val(); if (data !== null) { // dispatch成功的action,比如dispatch(setCurrentUser(data)) } }); } else { // 用户未登录时,清除Redux中的认证状态 // dispatch(logoutSuccess()) } }); }; };
核心要点总结:
- 用
await等待updateProfile完成,从根源避免异步顺序问题; user.reload()确保拿到服务器端最新的用户数据,不会被本地缓存坑;- 优化后的文档同步函数,既能创建新用户,也能同步后续的信息更新,保证数据库和Auth数据一致。
内容的提问来源于stack exchange,提问作者JonJon
相关产品推荐
相关产品推荐

