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

问题描述

我有一个奇怪的问题,当将TextInput放置在Child Functional Component内时,键盘在输入时会保持关闭状态.如果将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 组件.这意味着将创建每个渲染,新的 type 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 =()=>返回(...),然后在渲染时,像 {renderSignInForm()} 一样调用它,而不是< SignInForm/> .这样,它就不会像组件一样,也不会受到卸载的影响
  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时键盘被关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-25 04:56