Hi, I’m trying to refactor the code in firebase recapcha and separate it in to two screen, but it keep getting crash and show the error “can’t perform a react state update on an unmounted component. this is a no-op, but it indicates a memory leak in your application. to fix, cancel all subscriptions and asynchronous tasks in a useeffect cleanup function.” or “Can’t find variable useState”. Can someone show me how to solve this issue, please.
This is the link of Expo firebase recapcha
https://docs.expo.dev/versions/latest/sdk/firebase-recaptcha/
This is my code for the first screen
import React, { useState, useRef } from 'react'
import { StyleSheet, Text, View, Platform, TextInput, Button, TouchableOpacity } from 'react-native'
import { FirebaseRecaptchaVerifierModal, FirebaseRecaptchaBanner } from 'expo-firebase-recaptcha';
import { PhoneAuthProvider } from 'firebase/auth';
import { auth, app } from '../firebase'
// Double-check that we can run the example
if (!app?.options || Platform.OS === 'web') {
throw new Error('This example only works on Android or iOS, and requires a valid Firebase config.');
}
const PhoneNumberScreen = ({ navigation }) => {
const recaptchaVerifier = useRef(null);
const [phoneNumber, setPhoneNumber] = useState();
const [verificationId, setVerificationId] = useState();
const firebaseConfig = app ? app.options : undefined;
const [message, showMessage] = useState('');
const attemptInvisibleVerification = false;
const SendVerificationCode = async () => {
// The FirebaseRecaptchaVerifierModal ref implements the
// FirebaseAuthApplicationVerifier interface and can be
// passed directly to `verifyPhoneNumber`.
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.',
});
navigation.navigate('Confirm_Phone', { 'verificationId': verificationId })
} catch (err) {
showMessage({ text: `Error: ${err.message}`, color: 'red' });
}
}
return (
<View style={{ padding: 20, marginTop: 50 }}>
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={app.options}
// attemptInvisibleVerification
/>
<Text style={{ marginTop: 10, fontSize: 30 }}>Enter your phone number</Text>
<TextInput
style={{ marginVertical: 30, fontSize: 20, borderBottomWidth: 1 }}
placeholder="Ex: +1 999 999 9999"
autoFocus
autoCompleteType="tel"
keyboardType="phone-pad"
textContentType="telephoneNumber"
onChangeText={(phoneNumber) => setPhoneNumber(phoneNumber) }
/>
<Button
title="Send Verification Code"
style={styles.sendcodebutton}
disabled={!phoneNumber}
onPress={SendVerificationCode}
/>
{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>
)
}
export default PhoneNumberScreen
const styles = StyleSheet.create({
sendcodebutton: {
backgroundColor: 'rgba(90, 154, 230, 1)',
borderColor: 'transparent',
borderWidth: 0,
borderRadius: 30,
}
})
This is the second screen
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { PhoneAuthProvider, signInWithCredential } from 'firebase/auth';
import { auth, app } from '../firebase'
const ConfirmPhoneScreen = ({ route, navigation }) => {
const { verificationId } = route.params;
const [verificationCode, setVerificationCode] = useState();
const [message, showMessage] = useState();
const ConfirmVerificationCode = 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' });
}
}
return (
<View>
<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={ConfirmVerificationCode}
/>
</View>
)
}
export default ConfirmPhoneScreen
const styles = StyleSheet.create({})
I think that i have to use useEffect hook to clean up but I don’t know how. Please help me solve this problem.