问题描述
我有一个奇怪的问题,当 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.
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 = () =>return (...)
,并在渲染时,而不是像
{renderSignInForm()}
一样调用它.这样它就不会被当作组件对待,也不会被卸载
- 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 时键盘关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!