在 useRef() 对象 React-Native 组件中出现奇怪的行为
Getting weird behavior in useRef() object React-Native component
我正在使用 OTP 自动填充功能。我正在使用 react-native-otp-textinput,它工作正常。我正在为 OTP 文本字段使用 useRef(),所以当我收到短信时,我将使用此 useRef()
,并填写值。
问题陈述:
- 当我第一次 运行 应用程序时,我的
useRef()
表现良好,我可以自动用 userRef().current.setValue()
填充项目。
- 当我第二次或第三次运行这个应用程序时,我总是得到这个错误
TypeError: Cannot read property 'setValue' of null, js engine: hermes
我做的是捕捉,背后的原因是什么。所以我确实在我的功能中安慰了它。第一次发现,console.log(useRef().current)
打印数据,但是到了第二次或第三次,就returnsnull。我很困惑,为什么会这样?
这是我的代码:
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]);
我对此完全感到困惑,尝试跟进:。
编辑
这是我的 OTP TextInput 在 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
不应该用作ref
的数据类型,它应该 let
。原因是根据 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]);
我正在使用 OTP 自动填充功能。我正在使用 react-native-otp-textinput,它工作正常。我正在为 OTP 文本字段使用 useRef(),所以当我收到短信时,我将使用此 useRef()
,并填写值。
问题陈述:
- 当我第一次 运行 应用程序时,我的
useRef()
表现良好,我可以自动用userRef().current.setValue()
填充项目。 - 当我第二次或第三次运行这个应用程序时,我总是得到这个错误
TypeError: Cannot read property 'setValue' of null, js engine: hermes
我做的是捕捉,背后的原因是什么。所以我确实在我的功能中安慰了它。第一次发现,console.log(useRef().current)
打印数据,但是到了第二次或第三次,就returnsnull。我很困惑,为什么会这样?
这是我的代码:
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]);
我对此完全感到困惑,尝试跟进:
编辑
这是我的 OTP TextInput 在 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
不应该用作ref
的数据类型,它应该 let
。原因是根据 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]);