React中componentDidMount内异步处理Firebase用户状态并调用函数
解决React中等待Auth状态设置后调用函数的问题
嘿,我明白你的困扰——你想在componentDidMount里先完成用户状态的设置,再调用retrieveMatches,但之前的async/await用法没起作用,对吧?这是因为firebase.auth().onAuthStateChanged是基于回调的API,它不返回Promise,所以直接await它根本不会等待回调执行。而且setState本身也是异步的,就算在回调里设置了state,后面直接调用函数也拿不到最新的状态。
下面给你两种可行的解决方案:
方案一:使用setState的回调函数(推荐)
React的setState提供了第二个参数,这是一个回调函数,会在状态真正更新完成后触发。我们可以把retrieveMatches放在这个回调里,确保拿到最新的用户信息:
componentDidMount = () => { firebase.auth().onAuthStateChanged((user) => { if (user) { // setState的第二个参数是状态更新完成后的回调 this.setState({ user: user }, () => { this.props.retrieveMatches(this.state.user.uid); }); } else { // 别忘了处理没有用户登录的情况 console.log("当前没有用户登录"); } }); };
这样一来,只有当user状态完全更新到组件的state中后,才会调用retrieveMatches,完美解决时序问题。
方案二:将Auth监听包装成Promise(用async/await)
如果你坚持想用async/await,可以把onAuthStateChanged包装成Promise,同时把setState也转为Promise形式,确保等待所有异步操作完成:
componentDidMount = async () => { // 把onAuthStateChanged包装成Promise,获取当前用户 const user = await new Promise((resolve) => { // 拿到用户后取消监听,避免后续状态变化重复触发 const unsubscribe = firebase.auth().onAuthStateChanged((user) => { resolve(user); unsubscribe(); }); }); if (user) { // 把setState转为Promise,等待状态更新完成 await new Promise((resolve) => { this.setState({ user }, resolve); }); // 现在可以安全调用retrieveMatches了 this.props.retrieveMatches(this.state.user.uid); } else { console.log("当前没有用户登录"); } };
这个方法虽然能用,但比第一种复杂,一般更推荐方案一,因为它更符合React的设计习惯,代码也更简洁。
为什么你之前的async/await没用?
firebase.auth().onAuthStateChanged返回的是一个取消监听的函数,而不是Promise,所以await它不会等待回调执行,代码会直接跳到retrieveMatches那一行,这时候this.state.user还没被设置,自然会报错。
内容的提问来源于stack exchange,提问作者The Walrus
相关产品推荐
相关产品推荐

