React中如何在Firebase验证用户有效性后再发送POST请求
Firebase Auth状态未就绪时发送请求的解决方案
问题说明
当前通过以下代码获取Firebase用户的idToken并携带到后端请求:
const user = firebase.auth().currentUser const idToken = await user.getIdToken()
请求发送代码:
var res = await axios.post(backUrl + "account/load_balance", { uid: uid, id: id }, { headers: { Authorization: 'Bearer ' + idToken }});
多数场景下代码正常,但在特定页面中,请求会在user仍为null、idToken未生成时就发送到服务器。已知可以通过onAuthStateChanged方法监听用户状态,等待用户信息就绪后再触发逻辑,但不清楚如何集成到现有代码中。
现有代码问题
原组件中,useEffect仅依赖uid是否存在就调用loadBlockchainData,但Firebase的currentUser初始化是异步的——即使本地存储有uid,Firebase可能还未完成用户状态的同步,此时firebase.auth().currentUser会返回null,导致后续获取idToken失败。
集成onAuthStateChanged的方案
通过onAuthStateChanged监听用户登录状态,只有当确认用户已登录(user对象存在)时,再执行后端请求逻辑。同时要在组件卸载时移除监听,避免内存泄漏。
修改后的完整代码
const RoutingForPortfolio = (props) => { let uid = localStorage.getItem("account-info"); let { id } = useParams(); const loadBlockchainData = async (dispatch, user) => { if (id === null || id === undefined) { id = "test"; } // 直接使用监听回调传入的user对象,确保已就绪 const idToken = await user.getIdToken() console.log(idToken) var res = await axios.post(backUrl + "account/load_balance", { uid: uid, id: id }, { headers: { Authorization: 'Bearer ' + idToken }}); if (res.data === null) { await wait(2); document.location.href = "/logout" return; } else { const account = res.data.address; dispatch(web3AccountLoaded(account)); localStorage.setItem("account-address", account); if (res.data.token_flag && res.data.exchange_flag) { await dispatch(setLoginUserName(res.data.name)); await dispatch(setLoginUserEmail(res.data.email)); if (res.data.balance !== null) { await dispatch(etherBalanceLoaded(res.data.balance[0])); await dispatch(tokenBalanceLoaded(res.data.balance[1])); await dispatch(exchangeEtherBalanceLoaded(res.data.balance[2])); await dispatch(exchangeTokenBalanceLoaded(res.data.balance[3])); } } else { Swal.fire({ icon: "error", title: "Error...", text: "Error 485 - Please report to admin", }); return; } } }; useEffect(() => { // 注册用户状态监听 const unsubscribe = firebase.auth().onAuthStateChanged((user) => { // 仅当用户已登录且本地uid存在时,执行数据加载 if (user && uid) { loadBlockchainData(props.dispatch, user); } else if (!user && uid) { // 本地有uid但用户未登录,跳转到登录页 document.location.href = "/logout"; } }); // 组件卸载时移除监听 return () => unsubscribe(); }, [props.dispatch, uid]); return ( <> {uid ? ( <div> <Portfolio id={id} /> </div> ) : ( <Login /> )} </> ); };
关键修改点
- 将
loadBlockchainData改为接收user参数,确保使用的是已就绪的用户对象 - 在
useEffect中注册onAuthStateChanged监听,只有当user存在且本地uid有效时,才调用数据加载逻辑 - 添加监听的清理函数,组件卸载时取消监听,避免内存泄漏
- 增加了本地有
uid但用户未登录的处理,直接跳转登出
内容的提问来源于stack exchange,提问作者admin admin
相关产品推荐
相关产品推荐

