页面首次加载无法获取currentUser.uid,影响后端数据请求
解决Expo React Native中首次加载无法获取Firebase UID及触发后端请求的问题
问题根源
- Firebase Auth初始化时机问题:组件挂载时
auth.currentUser可能还未完成初始化,导致首次加载时无法读取到UID。 - React State异步更新特性:调用
setMyUserUID后立刻读取myUserUID,拿到的仍是旧的初始值,无法反映最新状态。 - 请求触发时机错误:
getUserInvoices在myUserUID和myIdToken未完全就绪时就被调用,导致请求URL中的UID为空,无法通过后端认证。
修复方案
import { StyleSheet, Text, View } from 'react-native' import React, { useEffect, useState } from 'react' import { auth } from '../firebase'; const InvoicesScreen = () => { const [myIdToken, setMyIdToken] = useState(''); const [myUserUID, setMyUserUID] = useState(''); const [userCurrency, setUserCurrency] = useState([]); // 监听用户认证状态变化,确保获取到稳定的用户实例 useEffect(() => { const unsubscribe = auth.onAuthStateChanged(async (user) => { if (user) { // 直接从user实例获取UID const uid = user.uid; setMyUserUID(uid); console.log('\nUser UID = ', uid, `\n`); // 获取ID Token const token = await user.getIdToken(); setMyIdToken(token); console.log('\n*********************************************************************************************************************************') console.log('\n\nUser Token: ', token, '\n'); } }); // 组件卸载时取消监听 return () => unsubscribe(); }, []); // 当UID和Token都就绪时,触发账单请求 useEffect(() => { async function getUserInvoices() { if (!myUserUID || !myIdToken) return; try { const response = await fetch(`https://testing123/${myUserUID}/details/all`, { headers: { 'Authorization': `Bearer ${myIdToken}` } }); const text = await response.json(); console.log('\n'); console.log('Invoice Info: ', text); console.log('\n'); // 使用函数式更新处理state闭包问题 setUserCurrency(prev => [...prev, ...text.map(item => item.amount.currency)]); console.log('\n*********************************************************************************************************************************'); } catch (error) { console.error('获取账单失败:', error); } } getUserInvoices(); }, [myUserUID, myIdToken]); // 依赖UID和Token,变化时重新执行 return ( <View style={styles.container}> <Text>InvoicesScreen</Text> </View> ) } export default InvoicesScreen const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center" } })
关键修改说明
- 监听Auth状态:使用
auth.onAuthStateChanged替代直接读取auth.currentUser,确保在用户认证状态稳定后再获取UID和Token,解决首次加载时用户实例未就绪的问题。 - 分离请求逻辑:将
getUserInvoices放在单独的useEffect中,依赖myUserUID和myIdToken,只有当这两个值都存在时才执行请求,保证参数完整。 - 修复State更新闭包:更新
userCurrency时使用函数式更新setUserCurrency(prev => ...),避免因闭包导致的旧state覆盖问题。 - 错误处理:添加
try/catch捕获请求过程中的错误,便于调试和异常处理。
内容的提问来源于stack exchange,提问作者confusedman
相关产品推荐
相关产品推荐

