React Native中Onpress事件如何等待异步函数执行完成再运行后续逻辑
React Native按钮首次点击不生效异步问题解决方案
核心问题原因
- Firebase的get查询是异步操作,原
noOpponent函数没有对外暴露异步完成的回调/Promise,调用后无法得知查询结束时机,后续判断逻辑会提前执行。 - React的状态更新为异步批量操作,就算
setOpponent执行完成,当前渲染闭包内的opponent变量仍然是旧值,无法立即读取到更新后的结果。
修改步骤
1. 改造noOpponent函数,返回异步查询结果
把原本在函数内更新状态的逻辑拆分,让函数直接返回查询得到的布尔结果,方便外部调用时等待异步完成。
export const noOpponent = async (Key) => { console.log("key: " + Key) const querySnapshot = await duettsRef .where("key", "==", Key) .where("player1", "!=", firebase.auth().currentUser.uid) .where("player2", "==", "") .limit(1) .get() const hasOpponent = !querySnapshot.empty console.log("QuerysnapshotResult: " + hasOpponent) return hasOpponent };
2. 改造按钮点击事件,用async/await等待异步结果
点击事件改为异步函数,等待查询结果返回后再执行后续的判断逻辑,同时新增加载状态防止重复点击。
const DuellScreen = () => { const [opponent, setOpponent] = useState(null); // 新增加载状态避免重复提交 const [loading, setLoading] = useState(false); const handleApplyPress = async () => { if (loading) return; try { setLoading(true); // 等待Firebase查询完成拿到结果 const hasOpponent = await noOpponent(code); // 可以保留状态更新供其他场景使用 setOpponent(hasOpponent); console.log("OPPONENT:" + hasOpponent); // 直接用拿到的结果做逻辑判断 if (hasOpponent) { setKeyToDuett(code); if (Platform.OS === "android") { ToastAndroid.show("Game joined!", ToastAndroid.SHORT); } else { Alert.alert("Game joined!"); } } else { const msg = "Game does not exist or someone else has already joined!"; if (Platform.OS === "android") { ToastAndroid.show(msg, ToastAndroid.SHORT); } else { Alert.alert(msg); } } } catch (err) { // 可自行补充网络异常、权限错误等场景的提示逻辑 console.error("查询失败:", err); } finally { setLoading(false); } }; return ( ... <BlockButton text={loading ? "处理中..." : "Apply"} onPress={handleApplyPress} disabled={loading} /> ... ) }
修改后点击按钮会等待Firebase查询完成再执行后续逻辑,首次点击即可拿到正确结果触发对应操作,无需二次点击。
内容的提问来源于stack exchange,提问作者Grrrrrag
相关产品推荐
相关产品推荐

