2022 Expo(React Native)如何无eject实现Firebase手机号认证
Expo SDK 44 免Eject接入Firebase 9.x手机号认证方案
完全可以实现,不需要执行eject操作。旧的Firebase 8适配教程失效是因为Firebase 9版本换成了模块化API,接口调用方式和8版本的命名空间写法差异很大,按照下面的步骤配置就能跑通:
依赖安装
执行以下命令安装兼容SDK 44的对应版本依赖,不要自行装过高版本避免兼容问题:expo install firebase@9.8.4 expo-firebase-recaptcha react-native-webviewFirebase控制台前置配置
- 进入对应项目的Authentication面板,开启手机号登录方式
- 在项目设置中添加Web应用,复制生成的Web端firebaseConfig配置项,不要使用iOS/Android原生端的配置
- 把开发阶段要用的测试手机号添加到手机号认证测试白名单,跳过真实短信下发和风控校验
核心实现代码(适配Firebase 9.8.4模块化API)
首先完成Firebase初始化:import { initializeApp } from 'firebase/app'; import { getAuth, signInWithPhoneNumber, signInWithCredential, PhoneAuthProvider } from 'firebase/auth'; import { FirebaseRecaptchaVerifierModal } from 'expo-firebase-recaptcha'; // 替换为你自己的Firebase Web端配置 const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "" }; const app = initializeApp(firebaseConfig); const auth = getAuth(app);登录页面逻辑参考:
import React, { useState, useRef } from 'react'; import { View, TextInput, Button, StyleSheet } from 'react-native'; export default function PhoneLogin() { const recaptchaVerifier = useRef(null); const [phoneNumber, setPhoneNumber] = useState(''); const [verifyCode, setVerifyCode] = useState(''); const [verificationId, setVerificationId] = useState(null); const sendCode = async () => { try { const verifier = recaptchaVerifier.current; const phoneRes = await signInWithPhoneNumber(auth, phoneNumber, verifier); setVerificationId(phoneRes.verificationId); } catch (err) { console.log('验证码发送失败:', err); } }; const login = async () => { try { const credential = PhoneAuthProvider.credential(verificationId, verifyCode); const res = await signInWithCredential(auth, credential); // 登录成功,可从res.user获取用户信息做后续跳转 console.log('登录成功', res.user); } catch (err) { console.log('登录失败:', err); } }; return ( <View style={styles.container}> <FirebaseRecaptchaVerifierModal ref={recaptchaVerifier} firebaseConfig={firebaseConfig} attemptInvisibleVerification={true} /> {!verificationId ? ( <> <TextInput style={styles.input} placeholder="输入手机号(格式:+8613xxxxxxxxx)" keyboardType="phone-pad" value={phoneNumber} onChangeText={setPhoneNumber} /> <Button title="发送验证码" onPress={sendCode} /> </> ) : ( <> <TextInput style={styles.input} placeholder="输入6位验证码" keyboardType="number-pad" value={verifyCode} onChangeText={setVerifyCode} /> <Button title="确认登录" onPress={login} /> </> )} </View> ) } const styles = StyleSheet.create({ container: { flex: 1, padding: 24, justifyContent: 'center' }, input: { borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 12, marginBottom: 16 } })常见踩坑说明
- 必须使用Firebase Web SDK实现,不要尝试接入原生端的Firebase认证模块,免eject的Expo环境不支持编译自定义原生代码
- 手机号必须带国际区号前缀,缺失区号会直接报无效参数错误
FirebaseRecaptchaVerifierModal组件不要做条件渲染,必须常驻页面渲染树,否则ref无法获取实例会导致reCAPTCHA初始化失败- 如果遇到reCAPTCHA无法加载的问题,在app.json的expo配置节点下添加
"scheme": "你的项目自定义名称",重启开发服务即可 - 生产环境如果要开隐形reCAPTCHA校验,需要在Firebase控制台把Expo应用的域名加到授权域名列表里
内容的提问来源于stack exchange,提问作者dany
相关产品推荐
相关产品推荐

