Expo集成Google登录后写入Firebase实时数据库遇触摸警告
问题排查与解决方案
一、触摸警告修复
你遇到的触摸相关警告,通常是Expo环境下Google登录弹窗与触摸事件系统冲突导致的,可通过以下方式解决:
- 替换触摸组件:将项目中的
TouchableOpacity/TouchableHighlight等组件替换为Expo官方推荐的Pressable组件,它对弹窗类交互的兼容性更好。 - 包裹异步回调:用
useCallback包裹onGoogleButtonPress函数,避免组件重复渲染导致触摸事件状态异常:const onGoogleButtonPress = useCallback(async () => { // 原函数逻辑 }, []); - 依赖版本适配:确保
@react-native-google-signin/google-signin版本与当前Expo SDK版本兼容,建议查看官方文档确认对应版本后升级。
二、Firebase数据写入逻辑修复
你的代码存在异步顺序错误和未定义变量问题,导致无法正确写入用户信息,以下是修正后的完整逻辑:
错误点说明
signInResult变量未定义,代码中直接使用了未声明的变量;- 调用
signInWithCredential后未等待异步完成就直接使用user.uid,此时组件状态user还未更新; - 数据库写入逻辑未放在登录成功的回调内,导致用户信息未正确获取。
修正后的代码
import { useState, useEffect, useCallback } from 'react'; import { Pressable, Text } from 'react-native'; import auth from '@react-native-firebase/auth'; import database from '@react-native-firebase/database'; import { GoogleSignin } from '@react-native-google-signin/google-signin'; export default function LoginScreen() { const [initializing, setInitializing] = useState(true); const [user, setUser] = useState(); GoogleSignin.configure({ webClientId: 'My_ID', // 替换为你的实际Web Client ID }); function onAuthStateChanged(user) { setUser(user); if (initializing) setInitializing(false); } useEffect(() => { const subscriber = auth().onAuthStateChanged(onAuthStateChanged); return subscriber; // 清理订阅 }, []); const onGoogleButtonPress = useCallback(async () => { try { // 检查Google Play服务 await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true }); // 获取Google登录结果 const googleUser = await GoogleSignin.signIn(); const { idToken } = googleUser; // 创建Firebase凭证 const googleCredential = auth.GoogleAuthProvider.credential(idToken); // 登录Firebase并获取用户凭证 const userCredential = await auth().signInWithCredential(googleCredential); const firebaseUser = userCredential.user; // 写入Firebase实时数据库 const userRef = database.ref(`/user_id/${firebaseUser.uid}`); await userRef.set({ email: firebaseUser.email, name: firebaseUser.displayName, photoURL: firebaseUser.photoURL, }); console.log('用户信息已成功写入数据库'); } catch (error) { console.error('登录或写入数据库失败:', error); } }, []); if (initializing) return null; return ( <Pressable onPress={onGoogleButtonPress}> <Text>Google登录</Text> </Pressable> ); }
关键修复点
- 使用
await等待所有异步操作完成,确保用户信息正确获取后再写入数据库; - 从
userCredential.user中直接获取用户信息,无需依赖组件状态更新; - 用
try/catch统一捕获所有异常,便于调试; - 用
useCallback包裹登录函数,避免不必要的重渲染。
内容的提问来源于stack exchange,提问作者Mahmoud Hlal
相关产品推荐
相关产品推荐

