[英]Expo react-native app with firebase phone authentication works on web, error on ios simulator and crashes with no warning on Android
我正在使用 expo 构建一个 react-native 应用程序,我只有 2 个组件,WelcomeScreen 和 PhoneLoginScreen。 I am trying to implement firebase phone authentication which works fine on the Web but on iOS Simulator I get an error Verifier._reset is not a function. (In 'verifier._reset()', 'verifiier._reset' is undefined
Verifier._reset is not a function. (In 'verifier._reset()', 'verifiier._reset' is undefined
,在 Android 上,当我单击导航到 PhoneLoginScreen 组件的继续按钮时,它会崩溃。代码如下:
应用程序.js
import React from "react"
import { NavigationContainer } from "@react-navigation/native"
import { createNativeStackNavigator } from "@react-navigation/native-stack"
import WelcomeScreen from "./components/WelcomeScreen"
import PhoneLoginScreen from "./components/auth/PhoneLoginScreen"
const Stack = createNativeStackNavigator()
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome">
<Stack.Screen
name="Welcome"
component={WelcomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="PhoneLogin"
component={PhoneLoginScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
WelcomeScreen.js
import React from "react"
import { Text, View, Button } from "react-native"
export default function WelcomeScreen({ navigation }) {
return (
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Welcome</Text>
<Button
title="Continue"
onPress={() => navigation.navigate("PhoneLogin")}
/>
</View>
)
}
PhoneLoginScreen.js
import React, { useRef, useState } from "react"
import { firebaseApp, auth } from "../../firebase"
import {
Text,
View,
TextInput,
Button,
StyleSheet,
TouchableOpacity,
} from "react-native"
import {
FirebaseRecaptchaVerifierModal,
FirebaseRecaptchaBanner,
} from "expo-firebase-recaptcha"
import { PhoneAuthProvider, signInWithCredential } from "firebase/auth"
export default function PhoneLoginScreen() {
const recaptchaVerifier = useRef(null)
const [message, showMessage] = useState()
const [phoneNumber, setPhoneNumber] = useState()
const [verificationId, setVerificationId] = useState()
const [verificationCode, setVerificationCode] = useState()
const firebaseConfig = firebaseApp ? firebaseApp.options : undefined
const attemptInvisibleVerification = true
return (
<View style={styles.center}>
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={firebaseConfig}
attemptInvisibleVerification={attemptInvisibleVerification}
/>
<Text style={{ marginTop: 20 }}>Enter phone number</Text>
<TextInput
style={{ marginVertical: 10, fontSize: 17 }}
placeholder="+1 999 999 9999"
autoFocus
autoCompleteType="tel"
keyboardType="phone-pad"
textContentType="telephoneNumber"
onChangeText={phoneNumber => setPhoneNumber(phoneNumber)}
/>
<Button
title="Send Verification Code"
disabled={!phoneNumber}
onPress={async () => {
try {
const phoneProvider = new PhoneAuthProvider(auth)
const verificationId =
await phoneProvider.verifyPhoneNumber(
phoneNumber,
recaptchaVerifier.current
)
setVerificationId(verificationId)
showMessage({
text: "Verification code has been sent to your phone.",
})
} catch (err) {
showMessage({
text: `Error 111: ${err.message}`,
color: "red",
})
}
}}
/>
<Text style={{ marginTop: 20 }}>Enter Verification code</Text>
<TextInput
style={{ marginVertical: 10, fontSize: 17 }}
editable={!!verificationId}
placeholder="123456"
onChangeText={setVerificationCode}
/>
<Button
title="Confirm Verification Code"
disabled={!verificationId}
onPress={async () => {
try {
const credential = PhoneAuthProvider.credential(
verificationId,
verificationCode
)
await signInWithCredential(auth, credential)
showMessage({
text: "Phone authentication successful 👍",
})
} catch (err) {
showMessage({
text: `Error: ${err.message}`,
color: "red",
})
}
}}
/>
{message ? (
<TouchableOpacity
style={[
StyleSheet.absoluteFill,
{
backgroundColor: 0xffffffee,
justifyContent: "center",
},
]}
onPress={() => showMessage(undefined)}>
<Text
style={{
color: message.color || "blue",
fontSize: 17,
textAlign: "center",
margin: 20,
}}>
{message.text}
</Text>
</TouchableOpacity>
) : undefined}
{attemptInvisibleVerification && <FirebaseRecaptchaBanner />}
</View>
)
}
const styles = StyleSheet.create({
center: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
})
firebase.js
import firebase from "firebase/compat/app"
import "firebase/compat/auth"
import "firebase/compat/firestore"
// Initialize Firebase
const firebaseConfig = {
// Config info...
}
let firebaseApp
if (firebase.apps.length === 0) {
firebaseApp = firebase.initializeApp(firebaseConfig)
} else {
firebaseApp = firebase.app()
}
const auth = firebase.auth()
export { auth, firebaseApp }
package.json 依赖项
"dependencies": {
"@react-navigation/native": "^6.0.6",
"@react-navigation/native-stack": "^6.2.5",
"expo": "~43.0.2",
"expo-firebase-recaptcha": "~2.0.2",
"expo-status-bar": "~1.1.0",
"firebase": "^9.5.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.8.0",
"react-native-web": "0.17.1",
"react-native-webview": "11.13.0"
}
我一直在谷歌上搜索,没有任何效果。 请指教
这是一个错误。 “expo-firebase-recaptcha”的维护者还没有发布修复,所以在那一天到来之前,这就是你自己修复它的方法:
Go 到 node_modules/expo-firebase-recaptcha,打开build
文件夹,找到FirebaseRecaptchaVerifierModal.js
。
在 FirebaseRecaptchaVerifierModal 内部,将以下 function 添加到组件定义中:
_reset = () => {}
在添加空的 function 定义后,我包含了文件的片段:
FirebaseRecaptchaVerifierModal.js
[...]
else {
this.setState({
visible: true,
visibleLoaded: false,
resolve,
reject,
});
}
});
}
/**
* Add the following line anywhere inside of the FirebaseRecaptchaVerifierModal component.
*/
_reset = () => {}
onVisibleLoad = () => {
this.setState({
visibleLoaded: true,
});
};
[...]
注意:您必须在每次安装 yarn/npm 或更改 node_modules 后执行此操作,直到发布者推送更新。
错误:verifier._reset 不是 function。 当尝试使用 firebase 使用手机登录时,反应原生和 Expo
FirebaseRecaptchaVerifierModal attemptInvisibleVerification Crashs on Android Emulator看看这个。这对我很有帮助
我加
`<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifierRef}
firebaseConfig={firebaseConfig}
androidHardwareAccelerationDisabled
tryInvisibleVerification />` 我的 FirebaseRecaptchaVerifierModal 上的这一行,这将有助于解决我的问题。
** 修复 EXPO 45、46 **
在网上冲浪寻求答案后,我失败了,找不到任何东西可以让它在 Expo 45 和 Expo 46 上工作,最后把它交给我了,因为我们无法使用手动 recaptcha 发布应用程序,因为它非常糟糕 UX . 因此,在尝试了 FirebaseRecaptchaVerifierModal 中所有可能的道具后,我终于找到了工作修复
通过结合所有修复并添加我自己发现的一个,我终于可以安心地 rest 了,因为这正在工作
// Declare the Timeout for Initial Page Load Fix
const [isInit, setisInit] = useState(false)
useEffect(() => {
setTimeout(function () {
setisInit(true)
}, 1000)
return () => {
setisInit(false)
}
}, [])
return(
<View>
...
{isInit && (
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={app.options}
androidHardwareAccelerationDisabled={true}
androidLayerType="software"
attemptInvisibleVerification
/>
)}
...
<FirebaseRecaptchaBanner />
</View>
这是神奇的线
androidLayerType="software"
我希望 Expo 在那里更新文档并避免我们所有开发人员的这种痛苦经历,我的意思是在我发送垃圾邮件之前,我真的从未见过带有手动 Recaptcha 的应用程序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.