Firebase手机认证创建用户后stripeId无法触发useEffect问题解决
问题:Firebase手机认证后StripeId无法触发useEffect钩子
在使用Google Firebase手机认证创建客户账号流程中,需为用户分配StripeId,完成后重定向至信用卡信息填写页面,但目前StripeId更新后无法触发页面中的useEffect钩子,导致后续获取Setup Intent的逻辑不执行。
现有代码
页面组件代码
const { authUser, loading } = useAuthUserContext(); const { email = '', displayName = '', stripeId = '' } = authUser || {}; useEffect(() => { if (authUser) { const { stripeId = '' } = authUser; if (stripeId) { fetch('/api/setup_intent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ customerId: stripeId }) }) .then((res) => res.json()) .then((data) => setClientSecret(data.clientSecret)); } } }, [authUser, loading, stripeId]);
Auth Context钩子代码
const [authUser, setAuthUser] = useState<IUser | null>(null); const authStateChanged = async (authState: any) => { if (!authState) { setLoading(false); return; } setLoading(true); const formattedUser = formatAuthUser(authState); setAuthUser(formattedUser); const { uid } = authState; const docRef = doc(firestore, 'users', uid); const snap = await getDoc(docRef); if (snap.exists()) { setAuthUser((f: any) => ({ ...f, ...snap.data() })); } setLoading(false); };
问题原因
当前代码使用getDoc仅一次性获取Firestore中的用户数据,而StripeId通常是在用户认证完成后,通过异步逻辑(比如创建Stripe客户后写入Firestore)添加到用户文档中的。此时getDoc已经执行完毕,无法感知后续StripeId的写入操作,导致authUser状态未更新,进而无法触发依赖authUser或stripeId的useEffect钩子。
修复方案
将一次性获取的getDoc替换为onSnapshot实时监听Firestore文档变化,这样当StripeId写入用户文档后,会自动触发快照更新,进而更新authUser状态,触发useEffect执行后续逻辑:
const [authUser, setAuthUser] = useState<IUser | null>(null); const authStateChanged = async (authState: any) => { if (!authState) { setLoading(false); return; } setLoading(true); const formattedUser = formatAuthUser(authState); setAuthUser(formattedUser); const { uid } = authState; const docRef = doc(firestore, 'users', uid); // 替换getDoc为onSnapshot实时监听文档变化 onSnapshot(docRef, (doc) => { if (doc.exists()) { setAuthUser((f: any) => ({ ...f, ...doc.data() })); } setLoading(false); }); };
额外说明:
onSnapshot会在文档首次获取和每次更新时触发,确保authUser能及时同步最新数据- useEffect的依赖数组中,
stripeId是从authUser解构而来,可仅保留authUser和loading作为依赖,避免冗余
内容的提问来源于stack exchange,提问作者Aleksandrs
相关产品推荐
相关产品推荐

