在嵌套的功能组件 React Native 中键入 TextInput 时键盘关闭 [英] Keyboard dismisses while typing TextInput in nested functional component React Native

查看:31
本文介绍了在嵌套的功能组件 React Native 中键入 TextInput 时键盘关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题,当 TextInput 被放置在子功能组件中时,键盘在打字时一直关闭.如果 TextInput 直接放置在父组件下,则不存在此问题.这是我的代码

I have this strange issue, keyboard keeps closing while typing when TextInput is placed inside Child Functional Component. This issue does not exist if TextInput is placed directly under Parent Component. Here is my code

const SignInScreenC = props => {

// define Hook states here    
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isEmailEmpty,setIsEmailEmpty] = useState(false);
const [isEmailValid,setIsEmailValid] = useState(true);
const [isPasswordEmpty,setIsPasswordEmpty] = useState(false);


/**
 * Called when Sign in is clicked.
 * checks if the form is valid
 */
 const _OnSignInClicked = () => {
   if(_isFormValid()) {
    //make api call
   }
 }

/* Checks if the form is valid
*/
const _isFormValid = () => {
   //reset values 
   setIsEmailEmpty(false);
   setIsEmailValid(true);
   setIsPasswordEmpty(false);

   let isValid = true;
   if(email.trim() === "") {
      setIsEmailEmpty(true);
      isValid = false;
    }
   else if(!AppUtils.isEmailValid(email)) {
      setIsEmailValid(false);
      isValid = false;
   }
   else if(password.trim() === "") {
      setIsPasswordEmpty(true);
      isValid = false;
   }
 return isValid;
}


const SignInForm = () => {
  return (

    <View style={styles.formStyle}>
    <TextInput
       key="email"
       label={Strings.hint_email}
       value={email}
       keyboardType="email-address"                            
       onChangeText={(text)=>  {
           setEmail(text)
           setIsEmailEmpty(false)
           setIsEmailValid(true)
       }}
       style={styles.marginStyle}
       autoCompleteType = "off"
       scrollEnabled = {false}
       autoCorrect={false}
       autoCapitalize={false}/>

       <TextInput
        key="pass"
        value={password}
        secureTextEntry ={true}
        label={Strings.hint_password}
        style={[styles.marginStyle,styles.stylePassword]}
        onChangeText={(text)=> {
             setPassword(text)
             setIsPasswordEmpty(false)}
        }
        theme="light"
        autoCompleteType = "off"
        scrollEnabled = {false}
        autoCorrect={false}
        autoCapitalize={false}/>
        <Button 
            style={styles.loginStyle}
            title = {Strings.login}
            onPressButton = {() => _OnSignInClicked()}/>

    </View>
  );
}

return ( 

    <>

        <ImageBackground source={Images.screen_backgound} style={{width: '100%', 
          height: '100%'}}>
            <View style = {styles.viewOverlaystyle} />
            <ScrollView  contentContainerStyle = {{flexGrow:1}} 
                keyboardShouldPersistTaps={'handled'}>
                <View style={styles.containerStyle}>
                    <SignInForm/>
                </View>
            </ScrollView>
        </ImageBackground>

    </>
 );
}

const styles = StyleSheet.create({
   ....
})

const mapStateToProps = state => ({
   userData : state.userData
});

const mapDispatchToProps = dispatch =>
    bindActionCreators(UserActions, dispatch);

 const SignInScreen = connect(mapStateToProps,mapDispatchToProps) (SignInScreenC)

 export {SignInScreen};

如果我粘贴所有内容

一切正常SignInForm> 直接渲染方法.

Everything works fine if I paste everything < SignInForm> directly to render method.

推荐答案

你的 SignInForm 函数(它被视为 React 组件,因为它大写并被称为 JSX)在你的 中声明SignInScreenC 组件.这意味着每次渲染,都会创建 React 组件的新类型.

your SignInForm function (which is treated like React component, because its capitalized and called as JSX) is declared inside your SignInScreenC component. This means that every render, new type of React component is created.

  1. SignInScreenC 第一次渲染:创建 SignInForm 组件,实例化它并渲染它
  2. SignInScreenC 第二次渲染:创建另一个完全不同的 SignInForm 组件,再次实例化它,有效地卸载旧的 SignInForm 并在其位置呈现新的 SignInForm
  3. 由于旧的输入被卸载,你失去了键盘焦点
  1. SignInScreenC renders first time: creates SignInForm component, instantiates it and renders it
  2. SignInScreenC renders second time: creates another, completely different SignInForm component, instantiates it again, effectively unmounting old SignInForm and rendering new SignInForm in it's place
  3. since old input is unmounted, you lose keyboard focus

这是由于 React 处理渲染的方式:每当遇到不同类型的元素应该被渲染来代替旧元素时,旧元素将被卸载.作为反应,每个新的 SignInForm 都与前一个不同,因为您不断地创建新功能

This is due to the way React handles rendering: whenever it encounters different type of element that should be rendered in place of an old element, old one will be unmounted. To react, every new SignInForm is different from the previous one as you keep constantly creating new functions

解决方案:

  1. SignInScreenC 之外创建单独的 SignInForm 组件并将所有必要的数据作为道具传递
  2. 或者,代替 const SignInForm = () =>return (...) 使用 const renderSignInForm = () =>return (...),并在渲染时,而不是 {renderSignInForm()} 一样调用它.这样它就不会被当作组件对待,也不会被卸载
  1. create separate SignInForm component outside of SignInScreenC and pass all the necessary data as props
  2. or, instead of const SignInForm = () => return (...) use const renderSignInForm = () => return (...), and while rendering, instead of <SignInForm/> call it like {renderSignInForm()}. This way it will not be treated like a component and will not be a subject to unmounts

这篇关于在嵌套的功能组件 React Native 中键入 TextInput 时键盘关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆