问题描述
我有一个奇怪的问题,当将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.
-
SignInScreenC
第一次渲染:创建SignInForm
组件,实例化并渲染 -
SignInScreenC
第二次渲染:创建另一个完全不同的SignInForm
组件,再次实例化它,有效地卸载了旧的SignInForm
并在其位置呈现新的SignInForm
- 由于卸载了旧的输入,因此您将失去键盘焦点
SignInScreenC
renders first time: createsSignInForm
component, instantiates it and renders itSignInScreenC
renders second time: creates another, completely differentSignInForm
component, instantiates it again, effectively unmounting oldSignInForm
and rendering newSignInForm
in it's place- 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
解决方案:
- 在
SignInScreenC
之外创建单独的SignInForm
组件,并将所有必要的数据作为道具传递 - 或者,而不是
const SignInForm =()=>return(...)
使用const renderSignInForm =()=>返回(...)
,然后在渲染时,像{renderSignInForm()}
一样调用它,而不是< SignInForm/>
.这样,它就不会像组件一样,也不会受到卸载的影响
- create separate
SignInForm
component outside ofSignInScreenC
and pass all the necessary data as props - or, instead of
const SignInForm = () => return (...)
useconst 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时键盘被关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!