我是React Native的完全菜鸟,我只是想摆脱它。
我有一个简单的登录屏幕,该屏幕是使用“容器/演示文稿”组件概念开发的。我的演示文稿组件仅具有渲染功能,可渲染三个TextInput和一个Button。
我不想在Toasts上显示错误,而是想在TextInput本身下面显示错误。因此,我所做的是在TextInput下面添加了Text元素。像下面这样。
<TextInput placeholder="Email"></TextInput>
<Text ref="emailErrors"></Text>
默认情况下,带有ref emailErrors的文本被隐藏。但是,当焦点从Email TextInput转移并且如果email由于某些原因无效时,我想生成一个简单的错误,并将其设置为带有ref emailErrors的Text元素的文本。
现在,我了解到我将不得不在容器组件中编写逻辑并将其作为prop传递给表示组件。但是我无法理解的是如何触发错误文本的设置并显示Text元素。
更新:
我的演示组件:
class LoginForm extends Component {
constructor(props) {
super(props);
}
render() {
return (
<KeyboardAvoidingView
style={styles.loginFormContainer}>
<ScrollView
scrollEnabled={true}
enableOnAndroid={true}
enableAutomaticScroll={true}
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="always"
resetScrollToCoords={{ x: 0, y: 0 }}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}>
<View style={styles.loginForm}>
<Image
source={require("../../../assets/images/logos/logo.png")}
style={styles.logoImage}></Image>
<View style={styles.textInputWithIcon}>
<Image
style={styles.textInputIcon}
source={require("../../../assets/images/icons/email.png")}
></Image>
<View style={styles.textField}>
<TextInput name="email"
ref="email"
placeholder="Email"
blurOnSubmit={false}
returnKeyType={"next"}
underlineColorAndroid={COLORS.red}
onSubmitEditing={() => this.refs.password.focus()}
style={[GLOBALSTYLES.textInput, styles.textInput]}
onChangeText={(text) => this.props.onEmailTextChanged(text)}
>
</TextInput>
<Text
ref="email">
</Text>
</View>
</View>
<View style={styles.textInputWithIcon}>
<Image
style={styles.textInputIcon}
source={require("../../../assets/images/icons/locked.png")}
></Image>
<View style={styles.textField}>
<TextInput name="password"
ref="password"
blurOnSubmit={false}
placeholder="Password"
secureTextEntry={true}
returnKeyType={"next"}
style={styles.textInput}
underlineColorAndroid={COLORS.red}
onSubmitEditing={() => Keyboard.dismiss()}
style={[GLOBALSTYLES.textInput, styles.textInput]}
onChangeText={(text) => this.props.onPasswordTextChanged(text)}
onBlur={() => this.props.onPasswordTextBlurred()}
></TextInput>
<Text
ref="password">
</Text>
</View>
</View>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => { this.props.onLoginPressed() }}
style={styles.loginButton}
underlayColor={COLORS.white}>
<Text style={styles.loginButtonText}>Login</Text>
</TouchableOpacity>
</View>
</ScrollView>
</KeyboardAvoidingView>
)
};
};
export default LoginForm;
我的容器组件:
class Login extends Component {
static navigationOptions = ({ navigation }) => ({
"title": "Login"
});
constructor(props) {
super(props);
this.state = {}
}
// onLoginPressed will trigger the authentication workflow with the remote server.
onLoginPressed() {
const { isUserLoggedIn, email, password } = this.state;
if (this.state.isEmailValid && this.state.isPasswordValid) {
axios.post(CONFIGURATION.LOGIN_URL, {
username: email,
password: password
}).then(response => {
const navigationParams = {
baseUrl: response.data.url,
token: response.data.token,
username: email
}
this.props.dispatch(loginSuccess(navigationParams));
// Adding retrieved values to AsyncStorage
AsyncStorage.multiSet(
[
[IS_USER_LOGGED_IN, "YES"],
[USER, email],
[TOKEN, response.data.token],
[BASE_URL, response.data.url]
],
() => {
this.props.navigation.navigate("WebApp", navigationParams);
});
}).catch(error => {
console.error(error);
ToastAndroid.show("Authentication Failed", ToastAndroid.SHORT);
});
}
}
// Updating the state key email
onEmailTextChanged(text) {
this.setState({ "email": text });
}
// Updating the state key password
onPasswordTextChanged(text) {
this.setState({ "password": text });
}
onEmailTextBlurred() {
var text = this.state.email;
console.warn(text);
if (text == undefined || text.trim().length == 0) {
this.setState({ "isEmailValid": false });
this.setState({ "emailErrorMessage": "Email cannot be empty" });
}
else {
var regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var isEmailValid = regex.test(text);
if (!isEmailValid) {
this.setState({ "isEmailValid": false });
this.setState({ "emailErrorMessage": "Email is incorrect." });
}
else {
this.setState({ "isEmailValid": true });
}
}
}
onPasswordTextBlurred() {
var text = this.state.password;
if (text == undefined || text.trim().length == 0) {
this.setState({ "isPasswordValid": false });
this.setState({ "passwordErrorMessage": "Password cannot be empty" });
}
else {
this.setState({ "isPasswordValid": true });
}
}
// rendering the LoginForm (presentational component) corresponding to this container component
render() {
return (
<LoginForm
onLoginPressed={() => this.onLoginPressed()}
onEmailTextChanged={(text) => this.onEmailTextChanged(text)}
onPasswordTextChanged={(text) => this.onPasswordTextChanged(text)}
onEmailTextBlurred={() => this.onEmailTextBlurred()}
onPasswordTextBlurred={() => this.onPasswordTextBlurred()}
/>
)
}
}
const mapStateToProps = (state) => {
return state;
}
const mapDispatchToProps = (dispatch) => {
const boundActionCreators = bindActionCreators(loginSuccess, dispatch);
return { ...boundActionCreators, dispatch };
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
答案 0 :(得分:1)
您可以在组件状态下使用标志,通过检查标志的状态来检查是否给出了无效输入。
例如:
emailValidationRegex(v){
// use regex to check if email is valid and return true if email is valid, false if email is invalid
}
<TextInput
placeholder="Email"
onChange={(v)=>{this.setState({
email: v,
isEmailInvalid: !emailValidationRegex(v)
})}} >
</TextInput>
{this.state.isEmailInvalid && <Text>Sorry! Invalid Email</Text>}
说明:
isEmailInvalid
保留给定电子邮件地址的状态(无论该地址是否有效)。根据其状态,有条件地显示以下错误。
更新:
在容器组件的onEmailTextChanged
方法中,如果电子邮件有效或无效,则将另一个状态更新为保留状态:
onEmailTextChanged(text) {
this.setState({ "email": text, isEmailInvalid: !emailValidationRegex(text) });
}
然后在发送给演示组件的道具中传递this.state.isEmailInvalid
。然后在演示组件中有条件地显示错误。
容器组件的渲染方法:
render() {
return (
<LoginForm
onLoginPressed={() => this.onLoginPressed()}
onEmailTextChanged={(text) => this.onEmailTextChanged(text)}
isEmailInvalid={this.state.isEmailInvalid}
onPasswordTextChanged={(text) => this.onPasswordTextChanged(text)}
onEmailTextBlurred={() => this.onEmailTextBlurred()}
onPasswordTextBlurred={() => this.onPasswordTextBlurred()}
/>
)
现在您可以在演示组件中使用this.props.isEmailInvalid