0

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:

  1. When I run the app for the first time, my useRef() behaves fine, and I can auto fill the item with userRef().current.setValue().
  2. When I run the app for the second or third time, I always get this error

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.

Edit

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)}
            />

enter image description here

14
  • I've never used the setValue method of useRef and cannot find any mention of it in the docs. Where did you see it? Commented Apr 13, 2021 at 10:49
  • 1
    @Konstantin setValue is a method of OTP text input (see the link in the question) Commented Apr 13, 2021 at 10:51
  • 2
    This probably won't address this particular issue, but in general when you access the ref, do ref.current?. instead of ref?.current (ref itself is always defined, but the current prop might not). Commented Apr 13, 2021 at 11:03
  • 1
    Hm... Maybe it should be let then instead if const. Does that component work at all? :) Commented Apr 13, 2021 at 11:13
  • 1
    Glad that it worked! I never had an opportunity to have a closer look at React Native so this was a good chance for me :) I used Snack and I like how it easily integrates and runs on my device. I'll add an answer, feel free to upvote it or edit if needed Commented Apr 13, 2021 at 12:25

1 Answer 1

1

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]);      
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Yuvin for the answer, I have improved the answer. Thank you for your suggestion :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.