How to integrate firebase-auth to verify phone number - firebase

I have created phone number verify screen and now I want to integrate firebase-auth for verifying phone number via OTP. But I have no idea how to do that, Please help me with it.
I have tried to find tutorial and example, but those were not helpful for me.
Phone Verify Screen
import React from 'react';
import {StyleSheet, View, TextInput, TouchableOpacity, Text, KeyboardAvoidingView, BackHandler, Alert, AsyncStorage, ToastAndroid } from 'react-native';
import HandleBack from '../component/backHandler';
import * as firebase from 'firebase';
class BuyerVerify extends React.Component{
componentDidMount(){
this.getData();
};
onBack = () => {
return true;
};
getData = () => {
const getNumber = async () => {
let number = '';
try {
number = await AsyncStorage.getItem('number');
} catch (error) {
// Error retrieving data
console.log(error.message);
}
//return number;
alert(number);
}
getNumber();
};
render(){
return(
<HandleBack onBack={this.onBack}>
<View style={styles.root}>
<View style={styles.outer}>
<View style={styles.inner}>
<KeyboardAvoidingView style={styles.container}>
<TextInput style={styles.input}
placeholder="Enter OTP"
placeholderTextColor="#939eaf"
keyboardType="phone-pad"
/>
<TouchableOpacity style={styles.button1Container}>
<Text style={styles.buttonText}>
Verify Buyer
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button2Container} onPress={()=> this.props.navigation.navigate('Main')}>
<Text style={styles.buttonText}>
Change number
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
</View>
</View>
</HandleBack>
);
}
}
export default BuyerVerify;
I want to verify phone number via OTP using firebase.

From Firebase's PhoneAuthProvider interface:
// 'recaptcha-container' is the ID of an element in the DOM.
var applicationVerifier = new firebase.auth.RecaptchaVerifier(
'recaptcha-container');
var provider = new firebase.auth.PhoneAuthProvider();
provider.verifyPhoneNumber('+16505550101', applicationVerifier)
.then(function(verificationId) {
var verificationCode = window.prompt('Please enter the verification ' +
'code that was sent to your mobile device.');
return firebase.auth.PhoneAuthProvider.credential(verificationId,
verificationCode);
})
.then(function(phoneCredential) {
return firebase.auth().signInWithCredential(phoneCredential);
});

Related

Error: [auth/unknown] Cannot create PhoneAuthCredential without either verificationProof, sessionInfo, temporary proof, or enrollment ID

I am trying to make a Login page with Phone Authentication to use React-Native-Firebase sdk and I receive OTP through sms and when I confirm the received OTP ,I got a error that: [Error: [auth/unknown] Cannot create PhoneAuthCredential without either verificationProof, sessionInfo, temporary proof, or enrollment ID.]
I am using-
React:18.0.0
React-Native: 0.69.1
React-Native-Firebase:^15.1.1
My code is-
import React, {useState} from 'react';
import {
View,
Text,
StyleSheet,
Image,
TextInput,
TouchableOpacity,
Alert,
} from 'react-native';
import PhoneInput from 'react-native-phone-number-input';
import auth from '#react-native-firebase/auth';
const Login = () => {
const [PhoneNumber, setPhoneNumber] = useState('');
const [otpInput, setOtpInput] = useState('');
const [confirmData, setConfirmData] = useState('');
const sendOtp = async () => {
try {
const responce = await auth().signInWithPhoneNumber(PhoneNumber);
setConfirmData(responce);
console.log(responce);
Alert.alert('Otp is sent please varify it');
} catch (error) {
console.log(error);
}
}
const submitOtp = async () => {
try {
const responce = await confirmData.confirm(otpInput);
console.log(responce);
Alert.alert('Your Number is verified');
} catch (error) {
console.log(error);
}
}
return (
<View>
<View style={styles.con}>
<Text style={styles.container}>Login Screen</Text>
<Image source={require('../assets/logo.png')} style={styles.image} />
</View>
<View style={styles.inputContainer}>
<Text style={styles.labels}>Phone Number:</Text>
<PhoneInput
style={styles.inputStyle}
defaultValue={PhoneNumber}
defaultCode="DM"
layout="first"
keyboardType="number-pad"
onChangeFormattedText={text => setPhoneNumber(text)}
onChangeText={(value) => setPhoneNumber(value)}
/>
</View>
<View>
<TouchableOpacity
style={styles.buttonStyle}>
<Text style={styles.buttonText}>Verify</Text>
</TouchableOpacity>
</View>
<View style={styles.otpContainer}>
<TextInput
style={styles.otpStyle}
placeholder="Enter OTP"
autoCapitalize="none"
secureTextEntry={true}
onChangeText={(value) => setOtpInput(value)}/>
</View>
<View>
<TouchableOpacity style={styles.continueStyle}>
<Text
style={styles.buttonText}
onPress={() => submitOtp()}>
Continue
</Text>
</TouchableOpacity>
</View>
</View>
);
};
export default Login;

Adding doc to firebase using react native and encountering many errors with promises/async storage

So im trying to make a todo list app and making the fucntion to add a doc to firebase. However, when i do that expo says the async storage has been deprecated and that there is a unhandled promise rejection
my code in my app:
import React, { useEffect } from 'react';
import {useState} from "react"
import { SafeAreaView, Text, View, Button, TouchableOpacity, Modal, StyleSheet,Pressable, TextInput } from 'react-native';
import { collection, doc, setDoc, query, getDocs, onSnapshot, addDoc, orderBy, limit, Timestamp, where} from "firebase/firestore";
import {db} from "../firebase"
import { signPlsOut } from '../firebase';
import { auth } from '../firebase';
import AsyncStorage from '#react-native-async-storage/async-storage';
export const Dashboard = () => {
const {uid, photoURL, displayName} = auth.currentUser;
const projectsref = collection(db, "projects");
const [modalVisible, setModalVisible] = useState(false);
const [projects, setProjects] = useState([])
const [desc, setDesc] = useState("");
const [title, setTitle] = useState("");
async function handleAddTask () {
try {
await addDoc(projectsref, {
title: title,
desc: desc,
createdAt: Timestamp.fromDate(new Date()),
uid: uid,
})
setTitle("")
setDesc("")
setModalVisible(false)
}
catch(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
// ADD THIS THROW error
throw error;
}
}
return (
<SafeAreaView>
<View style={{
margin: 20
}}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Add task:</Text>
<View style={{marginBottom: 20}}>
<TextInput placeholder='title' value={title} onChange={(e) => setTitle(e.target.value)}></TextInput>
<TextInput placeholder='description' value={desc} onChange={(e) => setDesc(e.target.value)}></TextInput>
</View>
<Button title='submit todo' onPress={handleAddTask}></Button>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>Cancel</Text>
</Pressable>
</View>
</View>
</Modal>
<Text style={{fontSize: 20, fontWeight: "500"}}>Welcome,</Text>
<Text style={{fontSize: 27, fontWeight: "700"}}>{auth.currentUser.email}</Text>
<View style={{marginTop: 30}}>
<Text style={{fontSize: 40, fontWeight: "700", color: "#0404"}}>Create Task</Text>
<TouchableOpacity>
<View style={{
backgroundColor: "orange",
borderRadius: "20px"
}}>
<Pressable
style={[styles.button, styles.buttonOpen]}
onPress={() => setModalVisible(true)}
>
<Text style={styles.textStyle}>Add task</Text>
</Pressable>
</View>
</TouchableOpacity>
</View>
<Button title="signout" onPress={signPlsOut}></Button>
</View>
</SafeAreaView>
);
};
error:
async sotrage has been extracted and will be removed in a future release, in addition to the unhandled promise rejection error
Are you able to actually add the doc to firebase? Some more context would be helpful in what you're trying to do. Is you code above completely unsucessful and you are getting errors? Or are you simply trying to clear errors.
If you are just trying to get rid of the unhandled promise rejection. I ran into a similar error and I found where in the Firebase app node_module where the call out was being for async storage. For me to get rid of a similar error i did two steps:
First, i installed the new react native async storage module:
npm install #react-native-async-storage/async-storage
Next, i had to update firebase app module, in the following file, to point to the appropriate API within my expo app to point to this new react native async storage module.
./node_modules/#firebase/app/dist/index.rn.cjs.js
I had to adjust this bit of code in this file:
var AsyncStorage = require('#react-native-async-storage/async-storage').AsyncStorage;
firebase.INTERNAL.extendNamespace({
INTERNAL: {
reactNative: {
AsyncStorage: AsyncStorage
}
}
});
The above code previously called to "react" i believe, i just needed to update it to specifically call to "#react-native-async-storage/async-storage". And this solved my problem.

TypeError: _this2.somefunction not a function

I'm trying to retrieve the status (parent/teacher/child) of the user I want to log in using the function checkStatusLogin, to redirect the user to the corresponding page
The problem is that I'm getting this error my console : Error getting document: [TypeError: _this2.checkStatusLogin is not a function. (In '_this2.checkStatusLogin(status)', '_this2.checkStatusLogin' is undefined)]
Here is my code :
import React from 'react';
import { ImageBackground,Image,ActivityIndicator, TouchableOpacity, StyleSheet, Text, View,TextInput,Dimensions } from 'react-native';
import background from "../Images/background.jpg";
import independoLogo from "../Images/Independo.png";
import firebase from 'firebase/app';
require('firebase/auth')
require('firebase/firestore')
const {width : WIDTH } = Dimensions.get('window')
const screenHeight=Dimensions.get('window').height
const screenWidth=Dimensions.get('window').width
class LoginAdult extends React.Component {
constructor(props){
super(props)
this.state={
email:'',
password:'',
isLoading:false,
}
this.checkStatusLogin=this.checkStatusLogin.bind(this);
}
checkStatusLogin(status)
{
alert("The user logged in");
console.log("checkStatus = ",status);
if(status==="Parent")
{
console.log("checkStatusParent = ",status);
this.props.navigation.navigate("HomeParent");
}
if(status==="Teacher")
{
console.log("checkStatusTeacher = ",status);
this.props.navigation.navigate("HomeTeacher");
}
if(status==="Child")
{
console.log("checkStatusTeacher = ",status);
this.props.navigation.navigate("HomeChild");
}
}
LoginPress= async()=>{
const {email,password,}=this.state;
global.stat;
if(this.state.email && this.state.password)
{
await firebase.auth().signInWithEmailAndPassword(email,password)
.then(firebase.auth().onAuthStateChanged(function(user)
{
if (user != null)
{
var docRef=firebase.firestore().collection("Users").doc(user.uid);
docRef.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
const {status} = doc.data();
console.log("Status = ",status);
this.checkStatusLogin(status);
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}
}))
.catch((error)=>{
switch(error.code)
{
case 'auth/invalid-email':
alert("Please, enter a valid mail")
break;
case 'auth/user-not-found':
alert('A user with this email doesnt exist, please sign Up')
break;
}
}
)
}
else{
alert("Please enter email and password!")
}
}
render(){
return (
<ImageBackground source={background} style={styles.imagebackground}>
<View style={{header:25,backgroundColor:"",alignItems:'center',marginTop:40}}>
<Image source={independoLogo} style={styles.logo}/>
</View>
<View style={{flex:1,borderWidth:0,borderColor:'transparent',margin:40,marginTop:0,marginBottom:220}}>
{this.state.isLoading?
<View style={{alignItems:'center',justifyContent:'center',zIndex:1000,elevation:1000}}>
<ActivityIndicator size="large" color="black"/>
</View>
:null}
<View style={{flex:1,backgroundColor:"#F9f3fc",alignItems:'center',paddingTop:35,borderRadius:15,borderStyle:'dotted solid double'}}>
<Text style={{fontWeight:'bold',fontSize:30,paddingBottom:30}}>LOGIN</Text>
<TextInput
style={styles.input}
placeholderTextColor={'black'}
placeholder={'Email'}
onChangeText={inputEmail=>this.setState({email:inputEmail})}/>
<TextInput
style={styles.input}
placeholderTextColor={'black'}
placeholder={'Password'}
secureTextEntry={true}
onChangeText={inputPassword=>this.setState({password:inputPassword})}/>
<TouchableOpacity style={styles.btnLogin} onPress={()=>this.LoginPress()}>
<Text style={{fontWeight:'600'}}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={{alignItems:'center',flexDirection:'row'}}
onPress={()=>this.props.navigation.navigate("SignUp")}>
<Text>Dont have an account? </Text>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
<TouchableOpacity
style={{alignItems:'center',flexDirection:'row',margin:4}}
onPress={()=>this.props.navigation.navigate("ForgotPasswordAdult")}>
<Text style={{textDecorationLine:'underline' ,fontSize:16 ,fontWeight:'bold',}}>
Forgot Password?
</Text>
</TouchableOpacity>
</View>
</View>
</ImageBackground>
);
}
}
export default LoginAdult;
const styles = StyleSheet.create({
});
Try removing the following line from your our code
this.checkStatusLogin = this.checkStatusLogin.bind(this);
delete the bind function and use an arrow function :
checkStatusLogin= (status) { ... }

undefined is not an object (evaluating '_this2.props') onPress

React native beginner here, Im trying to pass from login to HomeTeacher/HomeParent, according to the status in the database (firestore). When I'm printing the status, he is good ("Teacher"/"Parent"), but it doesnt go the HomeParent/HomeTeacher
When I press on the button I get the "Error getting document: [TypeError: undefined is not an object (evaluating '_this2.props.navigation')]" error...
Here is my code :
import React from 'react';
import { ImageBackground,Image, TouchableOpacity, StyleSheet, Text, View,TextInput,Dimensions } from 'react-native';
import background from "../Images/background.jpg";
import Logo from "../Images/Independo.png";
import firebase, { firestore } from 'firebase/app';
import { ThemeProvider } from 'react-native-elements';
require('firebase/auth')
require('firebase/firestore')
const {width : WIDTH } = Dimensions.get('window')
const screenHeight=Dimensions.get('window').height
const screenWidth=Dimensions.get('window').width
class LoginAdult extends React.Component {
constructor(props){
super(props)
this.state={
email:'',
password:'',
// status:''
}
}
LoginPress= async()=>{
const {email,password,}=this.state;
if(this.state.email && this.state.password)
{firebase.auth().signInWithEmailAndPassword(email,password)
.then(firebase.auth().onAuthStateChanged(function(user)
{
if (user != null)
{
var docRef=firebase.firestore().collection("Users").doc(user.uid);
docRef.get().then((doc) => {
if (doc.exists) {
console.log("Document data:", doc.data());
const {status} = doc.data();
if(status=="Teacher")
{
console.log("status = ",status)
this.props.navigation.navigate("HomeTeacher")
}
else if(status=="Parent")
{
this.props.navigation.navigate("HomeParent")
}
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}
}))
.catch((error)=>{
switch(error.code)
{
case 'auth/invalid-email':
alert("Please, enter a valid mail")
break;
case 'auth/user-not-found':
alert('A user with this email doesnt exist, please sign Up')
break;
}
})
}
else{
alert("Please enter email and password!")
}
}
render(){
return (
<ImageBackground source={background} style={styles.imagebackground}>
<View style={{header:25,backgroundColor:"",alignItems:'center',marginTop:40}}>
<Image source={Logo} style={styles.logo}/>
</View>
<View style={{flex:1,borderWidth:0,borderColor:'transparent',margin:40,marginTop:0,marginBottom:220}}>
<View style={{flex:1,backgroundColor:"#F9f3fc",alignItems:'center',paddingTop:35,borderRadius:15,borderStyle:'dotted solid double'}}>
<Text style={{fontWeight:'bold',fontSize:30,paddingBottom:30}}>LOGIN</Text>
<TextInput
style={styles.input}
placeholderTextColor={'black'}
placeholder={'Email'}
onChangeText={inputEmail=>this.setState({email:inputEmail})}/>
<TextInput
style={styles.input}
placeholderTextColor={'black'}
placeholder={'Password'}
secureTextEntry={true}
onChangeText={inputPassword=>this.setState({password:inputPassword})}/>
<TouchableOpacity style={styles.btnLogin} onPress={()=>this.LoginPress()}>
<Text style={{fontWeight:'600'}}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={{alignItems:'center',flexDirection:'row'}}
onPress={()=>this.props.navigation.navigate("SignUp")}>
<Text>Dont have an account? </Text>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
<TouchableOpacity
style={{alignItems:'center',flexDirection:'row',margin:4}}
onPress={()=>this.props.navigation.navigate("ForgotPasswordAdult")}>
<Text style={{textDecorationLine:'underline' ,fontSize:16 ,fontWeight:'bold',}}>
Forgot Password?
</Text>
</TouchableOpacity>
</View>
</View>
</ImageBackground>
);
}
}
export default LoginAdult;

How to pull key from firebase realtime database and pass to edit screen?

I am pretty new to react native/firebase, and am trying to figure out how to grab the unique key from an entry in the database (they are randomly generated when using Push), so I can update the database entry on my edit screen. Any help or direction on how I could accomplish this is very much appreciated.
Here is my main feed screen where all items from the database are grabbed and displayed:
let ref = db.ref('dogs');
export default class Main extends React.Component {
_isMounted = false;
constructor() {
super();
this.state = {
currentUser: null,
errorMessage: null,
items: [],
key: '',
};
}
componentDidMount() {
this._isMounted = true;
const {currentUser} = firebaseAuth;
this.setState({currentUser});
ref.on('value', snapshot => {
if (this._isMounted) {
let data = snapshot.val();
let items = Object.values(data);
this.setState({items});
}
});
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
const {currentUser} = this.state;
return (
<View style={styles.container}>
<View>
<View style={styles.container}>
{this.state.items.length > 0 ? (
<ItemComponent
style={styles.listDog}
items={this.state.items}
navigation={this.props.navigation}
/>
) : (
<Text>No dogs</Text>
)}
</View>
<View style={styles.bottomContainer}>
<TouchableOpacity
style={styles.addBtn}
onPress={() => this.props.navigation.navigate('dogCreation')}>
<View>
<FontAwesomeIcon style={styles.penIcon} icon={faBone} />
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
here is my item component:
export default class ItemComponent extends Component {
static propTypes = {
items: PropTypes.array.isRequired,
};
render() {
return (
<View style={styles.itemsList}>
{this.props.items.map((item, dog) => {
return (
<TouchableOpacity
key={dog}
onPress={() =>
this.props.navigation.navigate('Profile', {
name: item.name,
image_uri: item.image_uri,
parent: item.parent,
parentEmail: item.parentEmail,
parentTwo: item.parentTwo,
parentTwoEmail: item.parentTwoEmail,
})
}>
<View style={styles.dogCard}>
<Image source={{uri: item.image_uri}} style={styles.dogImage} />
<Text style={styles.itemtext}>{item.name} </Text>
<FontAwesomeIcon style={styles.chevron} icon={faChevronRight} />
</View>
</TouchableOpacity>
);
})}
</View>
);
}
}
here is my profile page:
export default class Profile extends React.Component {
render() {
const {navigation} = this.props;
const dogName = navigation.getParam('name', '');
const image_uri = navigation.getParam('image_uri', '');
const parent = navigation.getParam('parent', '');
const parentEmail = navigation.getParam('parentEmail', '');
const parentTwo = navigation.getParam('parentTwo', '');
const parentTwoEmail = navigation.getParam('parentTwoEmail', '');
return (
<View style={styles.container}>
<Image style={styles.dogImage} source={{uri: image_uri}} />
<View style={styles.contentBlock}>
<Text style={styles.header}>Name</Text>
<Text style={styles.textStyle}>{dogName}</Text>
</View>
<View style={styles.contentBlock}>
<Text style={styles.header}>Pet Parent 1 Info</Text>
<Text style={styles.subHeader}>Name</Text>
<Text style={styles.textStyle}>{parent}</Text>
<Text style={styles.subHeader}>Name</Text>
<Text style={styles.textStyle}>{parentEmail}</Text>
</View>
<View style={styles.contentBlock}>
<Text style={styles.header}>Pet Parent 2 Info</Text>
<Text style={styles.subHeader}>Name</Text>
<Text style={styles.textStyle}>{parentTwo}</Text>
<Text style={styles.subHeader}>Name</Text>
<Text style={styles.textStyle}>{parentTwoEmail}</Text>
</View>
<TouchableOpacity
style={styles.addBtn}
onPress={() =>
this.props.navigation.navigate('editProfile', {
name: dogName,
image_uri: image_uri,
parent: parent,
parentEmail: parentEmail,
parentTwo: parentTwo,
parentTwoEmail: parentTwoEmail,
})
}>
<Text>EDIT</Text>
</TouchableOpacity>
</View>
);
}
}
and here is my edit profile page update function:
let ref = db.ref('dogs');
let addItem = (
dog,
parent,
parentEmail,
parentTwo,
parentTwoEmail,
image_uri,
) => {
db.ref('/dogs/')
.update({
name: dog,
parent: parent,
parentEmail: parentEmail,
parentTwo: parentTwo,
parentTwoEmail: parentTwoEmail,
image_uri: image_uri,
});
};
just use on return snapshot return snapshot.key.
ref.on('value', snapshot => {
if (this._isMounted) {
let id = snapshot.key;
let data = snapshot.val();
let items = Object.values(data);
this.setState({items});
}
});
you can see more details here: https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#key
**some important points, if you are using the firebase library directly in react native, I advise you to use the version created specifically for React Native, which corrects several problems of timers within the OS.
you can see here: https://rnfirebase.io/
**other importante detail, your firebase return function is a listener, and using this._isMounted is anti patern. you can use subscriber to stop the listener.
so...
let subscriber;
...
componentDidMount() {
const {currentUser} = firebaseAuth;
this.setState({currentUser});
subscriber = ref.on('value', snapshot => {
let data = snapshot.val();
let items = Object.values(data);
this.setState({items});
});
}
componentWillUnmount() {
// Stop listening for updates when no longer required
this.subscriber();
}

Resources