I am working with the OTP auto-fill feature. I am using react-native-otp-textinput, which is working fine. I am using useRef() for the OTP Textfield, so when I receive a SMS, I will use this useRef()
, and fill it in the value.
Problem Statement:
useRef()
behaves fine, and I can auto fill the item with userRef().current.setValue()
.TypeError: Cannot read property 'setValue' of null, js engine: hermes
What I did was to capture, what was the reason behind it. So I did console it out in my function. I found out for the first time, console.log(useRef().current)
prints the data, but when it comes to second or third time, it returns null. I am confused, why is this happening?
Here is my code:
const otpInputRef = useRef(null);
const startReadSMSListerner = async () => {
// Checking permission, else getting one
const hasPermission = await ReadSms.requestReadSMSPermission();
// If given permission, start listening, else, leave it
if(hasPermission){
ReadSms.startReadSMS((status, sms, error) => {
if(status === 'success'){
console.log(otpInputRef.current); // <-- Comes fine for the first time, but null when we test it in the second time
otpInputRef?.current.setValue(sms); // <--- Here is the code which is working weird
}
});
}
}
useEffect(() => {
if(Platform.OS === 'android') startReadSMSListerner();
return () => ReadSms.stopReadSMS();
}, [otpInputRef]);
I am totally confused on this, tried following this up: TypeError: Cannot read property of setValue of null JavaScript.
Here is how my OTP TextInput looks in JSX
<OTPTextInput
ref={otpInputRef}
defaultValue=""
inputCount={4}
keyboardType="numeric"
returnKeyType="done"
textContentType="oneTimeCode" // for iOS Autofill enable
containerStyle={{justifyContent: 'center', padding: width / 15}}
textInputStyle={styles.textInputContainer}
handleTextChange={(text) => onChangetText(text)}
/>
const
should not be used as a datatype for the ref
, it should be let
. Reason being as per the lifecycle of React-Native:
View loads first, and useEffect updates afterwards, so const was just initialising ref value as null only. let enabled the ref useRef() value to update, and make the job easier
// This does the magic
let otpInputRef = useRef(null);
const startReadSMSListerner = async () => {
// Checking permission, else getting one
const hasPermission = await ReadSms.requestReadSMSPermission();
// If given permission, start listening, else, leave it
if(hasPermission){
ReadSms.startReadSMS((status, sms, error) => {
if(status === 'success'){
otpInputRef.current?.setValue(sms); // <--- Works now, since it gets updated in the useEffect() call
}
});
}
}
useEffect(() => {
if(Platform.OS === 'android') startReadSMSListerner();
return () => ReadSms.stopReadSMS();
}, [otpInputRef]);