javascript - onAuthStateChanged 被调用得太早
问题描述
我很想用一些额外的数据(例如:subscribeToEmail 字段等)创建一个新用户。根据我在网上阅读的内容,执行此操作的方法是对用户进行身份验证(例如:通过使用createUserWithEmailAndPassword
),然后使用uid
我从中获得的在用户集合中创建一个新文档。这就是我在下面尝试做的事情:
const handleSignup = async (formData) => {
const {email, password, ...otherUserData} = formData;
const {user} = await auth.createUserWithEmailAndPassword(email, password);
console.log("generating user doc at signup...");
await generateUserDocument(user, otherUserData); // creates user doc (called 2nd)
}
将使用从函数调用中获得的 uid 在集合中generateUserDocument
创建一个用户文档(如果它不存在) 。我还设置了一个身份验证状态更改事件处理程序:users
user
createUserWithEmailAndPassword
auth.onAuthStateChanged(async (userAuth) => { // get the current user
if (userAuth) {
const user = await generateUserDocument(userAuth); // user (should) already exists, so generateUserDocument will fetch the user rather than creating a new user doc, but this doesn't happen, as it is called 1st and not 2nd
dispatch(login(user)); // login logic
} else {
dispatch(logout());
}
});
createUserWithEmailAndPassword
这里的问题是,当我调用onAuthStateChanged
回调触发器时,它会generateUserDocument
在我实际使用generateUserDocument(user, otherUserData);
handleSignup 方法内部创建用户文档之前调用。换句话说, fetch user 方法: generateUserDocument
inside of.onAuthStateChange()
是在实际创建用户之前调用的,这是由方法generateUserDocument
内部完成的handleSignup
。因此,我在 authStateChange 中获取的用户数据不包括我所追求的详细信息。
有没有办法解决这个问题,以便在 onAuthStateChange 事件处理程序执行之前(而不是之后)auth.createuserWithEmailAndPassword()
调用我的函数调用?我已经考虑过使用类似的东西,但我认为这可能有点矫枉过正,因为用户数据表不应该真的需要被连续收听,因为它很少会改变。最好有一个生命周期方法在我可以用来填充我的用户集合之前被调用,但我还没有找到太多关于它的东西。.onSnapshot()
onAuthStateChanged
作为参考,我一直在关注这篇关于将其他用户数据与 auth-user 记录相关联的文章。
解决方案
有没有办法解决这个问题,以便
auth.createuserWithEmailAndPassword()
在onAuthStateChange
事件处理程序执行之前(而不是之后)调用我的函数调用?
不,没有开箱即用的方法,因为
- 成功创建用户帐户后,
createuserWithEmailAndPassword()
该用户也将登录到您的应用程序(请参阅文档),并且 onAuthStateChange()
观察者在登录或注销时触发。
因此,您确实需要等待创建用户 Firestore 文档,然后再继续。在我看来,最好的方法是你提到的那个,即为user
文档设置一个监听器。
您可以这样做,在您第一次从用户文档中获取数据后立即取消侦听器,如下所示。这样用户文档就不会被连续收听。
auth.onAuthStateChanged((userAuth) => { // No more need to be async
// get the current user
if (userAuth) {
const userDocRef = firestore.collection('users').doc(userAuth.uid);
const listener = userDocRef.onSnapshot((doc) => {
if (doc.exists) {
console.log(doc.data());
// Do any other action you need with the user's doc data
listener(); // Calling the unsubscribe function that cancels the listener
dispatch(login(user));
}
});
} else {
dispatch(logout());
}
});
另一种方法可能是使用Callable Cloud Function,它在后端在 Auth 服务中创建用户并在 Firestore 中创建文档。您的handleSignup
功能如下:
const handleSignup = async (formData) => {
const createUser = firebase.functions().httpsCallable('createUser');
await createUser({formData});
// The user is created in the Auth service
// and the user doc is created in Firestore
// We then need to signin the user, since the call to the Cloud Function did not do it!
const {email, password, ...otherUserData} = formData;
await auth.signInWithEmailAndPassword(email, password);
// The onAuthStateChanged listener is triggered and the Firestore doc does exist
}
推荐阅读
- javascript - 将 JWT 令牌用于用户和应用程序
- ios - 为什么 Swift 对象在 Objective-C 代码中被声明/未声明为属性时表现不同?
- python - 使用Python进行语音分析)如何在x轴上及时查看语音文件的分析结果,在y轴上查看分贝数?
- c# - Onion Architecture - 需要来自基础设施的信息的领域模型方法
- javascript - onMouseLeave 与 Chrome 密码存储菜单的交互
- forms - Flutter 错误“构建函数返回 null”
- html - 在 angular2 中,每当列表更改时,它都会选择第一个元素,那么如何避免呢?
- sql - 有没有更好的方法来编写这个 Access SQL 表达式?
- reactjs - 在 redux 中集成 reselect
- java - 如何从 pojo 生成数组对象并在 Java 中传入 formparams