admin管理员组文章数量:1026989
Firebase Phone Auth Integration Error in Expo (NOBRIDGE) Problem
I'm trying to implement Firebase Phone Authentication in my Expo React Native app but getting the following error:
ERROR Error: Native module RNFBAppModule not found. Re-check module install, linking, configuration, build and install steps.
Environment
Expo SDK:"~52.0.23",
"react": "18.3.1",
"react-native": "0.76.5",
"@react-native-firebase/app": "^21.6.1",
"@react-native-firebase/auth": "^21.6.1",
Platform: iOS/Android
What I've Tried
Installed Firebase:
npx expo install @react-native-firebase/app
Added Firebase configuration in app.json:
{ "expo": { "plugins": [ "@react-native-firebase/app" ] } }
Set up firebase-config.js with proper credentials
Code
Here's my login screen implementation:
import React, { useState } from 'react';
import {
View, Text, TextInput, TouchableOpacity, SafeAreaView,
StyleSheet, KeyboardAvoidingView, Platform, Keyboard,
TouchableWithoutFeedback, Alert
} from 'react-native';
import { Phone, Package, ArrowRight } from 'lucide-react-native';
import { useUser } from './context/UserContext';
import { auth } from '../firebase.config';
import { PhoneAuthProvider, signInWithCredential } from 'firebase/auth';
const LoginScreen = () => {
const [phoneNumber, setPhoneNumber] = useState('');
const [otpSent, setOtpSent] = useState(false);
const [otp, setOtp] = useState('');
const [error, setError] = useState('');
const [verificationId, setVerificationId] = useState(null);
const { updateUserData } = useUser();
const handleSendOTP = async () => {
try {
const phoneRegex = /^[0-9]{10}$/;
if (!phoneRegex.test(phoneNumber)) {
setError('Please enter a valid 10-digit phone number');
return;
}
const formattedPhone = `+91${phoneNumber}`; // Adjust country code
const appVerifier = {
type: 'recaptcha',
verify: () => Promise.resolve('dummy-token')
};
const verificationId = await PhoneAuthProvider.verifyPhoneNumber(
auth,
formattedPhone,
appVerifier
);
setVerificationId(verificationId);
setOtpSent(true);
setError('');
Alert.alert('OTP Sent', 'Please check your phone for the verification code');
} catch (err) {
setError('Failed to send OTP. Please try again.');
console.error('Send OTP error:', err);
}
};
const handleVerifyOTP = async () => {
try {
if (otp.length !== 6) {
setError('Please enter a 6-digit OTP');
return;
}
const credential = PhoneAuthProvider.credential(verificationId, otp);
const userCredential = await signInWithCredential(auth, credential);
updateUserData({
phone: phoneNumber,
isLoggedIn: true,
uid: userCredential.user.uid
});
setError('');
} catch (err) {
setError('Invalid OTP. Please try again.');
console.error('Verify OTP error:', err);
}
};
return (
<SafeAreaView style={styles.container}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardContainer}
>
<View style={styles.header}></View>
<View style={styles.content}>
<View style={styles.logoContainer}>
<Package color="#FF85A2" size={64} />
<Text style={styles.welcomeText}>Welcome to Pink Parcel</Text>
<Text style={styles.subtitleText}>Your premium delivery partner</Text>
</View>
{!otpSent ? (
<View style={styles.inputSection}>
<View style={styles.inputContainer}>
<Phone color="#FF85A2" size={24} style={styles.inputIcon} />
<TextInput
placeholder="Enter Phone Number"
placeholderTextColor="#8F90A6"
keyboardType="phone-pad"
value={phoneNumber}
onChangeText={setPhoneNumber}
maxLength={10}
style={styles.input}
/>
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleSendOTP}
>
<Text style={styles.buttonText}>Send OTP</Text>
<ArrowRight color="#FFFFFF" size={20} />
</TouchableOpacity>
</View>
) : (
<View style={styles.inputSection}>
<View style={styles.inputContainer}>
<Package color="#E91E63" size={24} style={styles.inputIcon} />
<TextInput
placeholder="Enter 6-digit OTP"
placeholderTextColor="#8F90A6"
keyboardType="number-pad"
value={otp}
onChangeText={setOtp}
maxLength={6}
style={styles.input}
/>
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleVerifyOTP}
>
<Text style={styles.buttonText}>Verify OTP</Text>
<ArrowRight color="#FFFFFF" size={20} />
</TouchableOpacity>
<TouchableOpacity
style={styles.secondaryButton}
onPress={() => setOtpSent(false)}
>
<Text style={styles.secondaryButtonText}>Change Phone Number</Text>
</TouchableOpacity>
</View>
)}
{error ? (
<Text style={styles.errorText}>{error}</Text>
) : null}
</View>
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFF5F8',
},
keyboardContainer: {
flex: 1,
},
header: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 60,
backgroundColor: '#FFF5F8',
borderBottomWidth: 1,
borderBottomColor: '#FFF5F8',
},
headerTitle: {
fontSize: 20,
fontWeight: '700',
color: '#2D2D3A',
},
content: {
flex: 1,
padding: 20,
},
logoContainer: {
alignItems: 'center',
marginVertical: 40,
},
welcomeText: {
fontSize: 24,
fontWeight: '700',
color: '#2D2D3A',
marginTop: 16,
marginBottom: 8,
},
subtitleText: {
fontSize: 16,
color: '#8F90A6',
},
inputSection: {
backgroundColor: '#FFFFFF',
borderRadius: 24,
padding: 20,
shadowColor: '#E91E63',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.08,
shadowRadius: 12,
elevation: 5,
},
inputContainer: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#FFE4EC',
marginBottom: 20,
paddingVertical: 8,
},
inputIcon: {
marginRight: 12,
},
input: {
flex: 1,
height: 50,
fontSize: 16,
color: '#2D2D3A',
},
primaryButton: {
backgroundColor: '#E91E63',
borderRadius: 16,
paddingVertical: 14,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
gap: 8,
},
buttonText: {
color: '#FFFFFF',
fontSize: 15,
fontWeight: '600',
},
secondaryButton: {
paddingVertical: 14,
alignItems: 'center',
marginTop: 12,
},
secondaryButtonText: {
color: '#E91E63',
fontSize: 15,
fontWeight: '600',
},
errorText: {
color: '#E91E63',
textAlign: 'center',
marginTop: 16,
fontSize: 14,
},
});
export default LoginScreen;
Expected Behavior
Firebase Phone Authentication should work in my Expo app.
Actual Behavior
Getting NOBRIDGE error indicating native module is not found.
Can anyone help identify what I'm missing in the setup?
Firebase Phone Auth Integration Error in Expo (NOBRIDGE) Problem
I'm trying to implement Firebase Phone Authentication in my Expo React Native app but getting the following error:
ERROR Error: Native module RNFBAppModule not found. Re-check module install, linking, configuration, build and install steps.
Environment
Expo SDK:"~52.0.23",
"react": "18.3.1",
"react-native": "0.76.5",
"@react-native-firebase/app": "^21.6.1",
"@react-native-firebase/auth": "^21.6.1",
Platform: iOS/Android
What I've Tried
Installed Firebase:
npx expo install @react-native-firebase/app
Added Firebase configuration in app.json:
{ "expo": { "plugins": [ "@react-native-firebase/app" ] } }
Set up firebase-config.js with proper credentials
Code
Here's my login screen implementation:
import React, { useState } from 'react';
import {
View, Text, TextInput, TouchableOpacity, SafeAreaView,
StyleSheet, KeyboardAvoidingView, Platform, Keyboard,
TouchableWithoutFeedback, Alert
} from 'react-native';
import { Phone, Package, ArrowRight } from 'lucide-react-native';
import { useUser } from './context/UserContext';
import { auth } from '../firebase.config';
import { PhoneAuthProvider, signInWithCredential } from 'firebase/auth';
const LoginScreen = () => {
const [phoneNumber, setPhoneNumber] = useState('');
const [otpSent, setOtpSent] = useState(false);
const [otp, setOtp] = useState('');
const [error, setError] = useState('');
const [verificationId, setVerificationId] = useState(null);
const { updateUserData } = useUser();
const handleSendOTP = async () => {
try {
const phoneRegex = /^[0-9]{10}$/;
if (!phoneRegex.test(phoneNumber)) {
setError('Please enter a valid 10-digit phone number');
return;
}
const formattedPhone = `+91${phoneNumber}`; // Adjust country code
const appVerifier = {
type: 'recaptcha',
verify: () => Promise.resolve('dummy-token')
};
const verificationId = await PhoneAuthProvider.verifyPhoneNumber(
auth,
formattedPhone,
appVerifier
);
setVerificationId(verificationId);
setOtpSent(true);
setError('');
Alert.alert('OTP Sent', 'Please check your phone for the verification code');
} catch (err) {
setError('Failed to send OTP. Please try again.');
console.error('Send OTP error:', err);
}
};
const handleVerifyOTP = async () => {
try {
if (otp.length !== 6) {
setError('Please enter a 6-digit OTP');
return;
}
const credential = PhoneAuthProvider.credential(verificationId, otp);
const userCredential = await signInWithCredential(auth, credential);
updateUserData({
phone: phoneNumber,
isLoggedIn: true,
uid: userCredential.user.uid
});
setError('');
} catch (err) {
setError('Invalid OTP. Please try again.');
console.error('Verify OTP error:', err);
}
};
return (
<SafeAreaView style={styles.container}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardContainer}
>
<View style={styles.header}></View>
<View style={styles.content}>
<View style={styles.logoContainer}>
<Package color="#FF85A2" size={64} />
<Text style={styles.welcomeText}>Welcome to Pink Parcel</Text>
<Text style={styles.subtitleText}>Your premium delivery partner</Text>
</View>
{!otpSent ? (
<View style={styles.inputSection}>
<View style={styles.inputContainer}>
<Phone color="#FF85A2" size={24} style={styles.inputIcon} />
<TextInput
placeholder="Enter Phone Number"
placeholderTextColor="#8F90A6"
keyboardType="phone-pad"
value={phoneNumber}
onChangeText={setPhoneNumber}
maxLength={10}
style={styles.input}
/>
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleSendOTP}
>
<Text style={styles.buttonText}>Send OTP</Text>
<ArrowRight color="#FFFFFF" size={20} />
</TouchableOpacity>
</View>
) : (
<View style={styles.inputSection}>
<View style={styles.inputContainer}>
<Package color="#E91E63" size={24} style={styles.inputIcon} />
<TextInput
placeholder="Enter 6-digit OTP"
placeholderTextColor="#8F90A6"
keyboardType="number-pad"
value={otp}
onChangeText={setOtp}
maxLength={6}
style={styles.input}
/>
</View>
<TouchableOpacity
style={styles.primaryButton}
onPress={handleVerifyOTP}
>
<Text style={styles.buttonText}>Verify OTP</Text>
<ArrowRight color="#FFFFFF" size={20} />
</TouchableOpacity>
<TouchableOpacity
style={styles.secondaryButton}
onPress={() => setOtpSent(false)}
>
<Text style={styles.secondaryButtonText}>Change Phone Number</Text>
</TouchableOpacity>
</View>
)}
{error ? (
<Text style={styles.errorText}>{error}</Text>
) : null}
</View>
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFF5F8',
},
keyboardContainer: {
flex: 1,
},
header: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 60,
backgroundColor: '#FFF5F8',
borderBottomWidth: 1,
borderBottomColor: '#FFF5F8',
},
headerTitle: {
fontSize: 20,
fontWeight: '700',
color: '#2D2D3A',
},
content: {
flex: 1,
padding: 20,
},
logoContainer: {
alignItems: 'center',
marginVertical: 40,
},
welcomeText: {
fontSize: 24,
fontWeight: '700',
color: '#2D2D3A',
marginTop: 16,
marginBottom: 8,
},
subtitleText: {
fontSize: 16,
color: '#8F90A6',
},
inputSection: {
backgroundColor: '#FFFFFF',
borderRadius: 24,
padding: 20,
shadowColor: '#E91E63',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.08,
shadowRadius: 12,
elevation: 5,
},
inputContainer: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#FFE4EC',
marginBottom: 20,
paddingVertical: 8,
},
inputIcon: {
marginRight: 12,
},
input: {
flex: 1,
height: 50,
fontSize: 16,
color: '#2D2D3A',
},
primaryButton: {
backgroundColor: '#E91E63',
borderRadius: 16,
paddingVertical: 14,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
gap: 8,
},
buttonText: {
color: '#FFFFFF',
fontSize: 15,
fontWeight: '600',
},
secondaryButton: {
paddingVertical: 14,
alignItems: 'center',
marginTop: 12,
},
secondaryButtonText: {
color: '#E91E63',
fontSize: 15,
fontWeight: '600',
},
errorText: {
color: '#E91E63',
textAlign: 'center',
marginTop: 16,
fontSize: 14,
},
});
export default LoginScreen;
Expected Behavior
Firebase Phone Authentication should work in my Expo app.
Actual Behavior
Getting NOBRIDGE error indicating native module is not found.
Can anyone help identify what I'm missing in the setup?
本文标签:
版权声明:本文标题:reactjs - Error: Native module RNFBAppModule not found. Re-check module install, linking, configuration, build and install steps 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1735952656a1365902.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论