我有以下 React 组件,它包含一个带有两个输入和一个按钮的表单。
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: null,
password: null
}
}
emailInputChanged = (e) => {
this.setState({
email: e.target.value.trim()
});
};
passwordInputChanged = (e) => {
this.setState({
password: e.target.value.trim()
});
};
loginButtonClicked = (e) => {
e.preventDefault();
if (!this.isFormValid()) {
//Perform some API request to validate data
}
};
signupButtonClicked = (e) => {
e.preventDefault();
this.props.history.push('/signup');
};
forgotPasswordButtonClicked = (e) => {
e.preventDefault();
this.props.history.push('/forgot-password');
};
isFormValid = () => {
const {email, password} = this.state;
if (email === null || password === null) {
return false;
}
return isValidEmail(email) && password.length > 0;
};
render() {
const {email, password} = this.state;
return (
<div id="login">
<h1 className="title">Login</h1>
<form action="">
<div className={(!isValidEmail(email) ? 'has-error' : '') + ' input-holder'}>
<Label htmlFor={'loginEmail'} hidden={email !== null && email.length > 0}>email</Label>
<input type="text" className="input" id="loginEmail" value={email !== null ? email : ''}
onChange={this.emailInputChanged}/>
</div>
<div className={(password !== null && password.length === 0 ? 'has-error' : '') + ' input-holder'}>
<Label htmlFor={'loginPassword'}
hidden={password !== null && password.length > 0}>password</Label>
<input type="password" className="input" id="loginPassword"
value={password !== null ? password : ''}
onChange={this.passwordInputChanged}/>
</div>
<button type="submit" className="btn btn-default" id="loginButton"
onClick={this.loginButtonClicked}>
login
</button>
</form>
<div className="utilities">
<a href={'/signup'} onClick={this.signupButtonClicked}>don't have an account?</a>
<a href={'/forgot-password'} onClick={this.forgotPasswordButtonClicked}>forgot your password?</a>
</div>
</div>
)
}
}
export function isValidEmail(email) {
const expression = /\S+@\S+/;
return expression.test(String(email).toLowerCase());
}
输入的值存储在组件的 state
中。我给了它们初始值 null
并使用 setState()
更新它们在 onChange
事件。
在 render()
方法我使用状态为具有无效值的输入着色。目前,我仅根据简单的正则表达式检查电子邮件值,并且密码长度至少为 1 个字符。
我将状态变量的初始值设置为 null
的原因所以我可以检查输入的布局和初始样式,使其不被标记为 "has-errors"
。但是我需要将检查扩展到:
this.state.email !== null && this.state.email.length === 0
为了工作,因为 null 没有 length
属性。
是否有一种更干净且“React-ish”的方式来实现这一目标:
- 保存输入的 div 的初始状态没有类 has-errors
- 设置 value
时检查较少输入上的属性(因为 React 不接受 null
作为属性值)
this.state.email
和this.state.password
是空字符串,我得到 has-error
应用于保存输入的 div。在我看来,这是糟糕的用户体验,因为用户没有做任何事情,而且他已经错了。
hidden
属性由我制作的自定义组件使用,其作用类似于“占位符”(如果在输入中键入某些内容,则会被删除)。
下面的视频显示了当 this.state.email
时我的表单的样子和this.state.password
也是空字符串以及我的<Label>
组件工作原理:
最佳答案
您可以创建一个验证函数,该函数返回一个错误对象以了解哪些字段出现错误,并使用空字符串作为初始值。我不明白你想用隐藏属性做什么。
编辑:在状态中添加触摸属性,以了解哪个字段被触摸。
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
touched: {},
};
}
emailInputChanged = e => {
this.setState({
email: e.target.value.trim(),
touched: {
...this.state.touched,
email: true,
},
});
};
passwordInputChanged = e => {
this.setState({
password: e.target.value.trim(),
touched: {
...this.state.touched,
password: true,
},
});
};
loginButtonClicked = e => {
e.preventDefault();
if (!this.isFormValid()) {
//Perform some API request to validate data
}
};
isFormValid = () => {
const errors = this.validate();
return Object.keys(errors).length === 0;
};
validate = () => {
const errors = {};
const { email, password } = this.state;
if (!isValidEmail(email)) {
errors.email = true;
}
if (password.length === 0) {
errors.password = true;
}
return errors;
};
render() {
const { email, password, touched } = this.state;
const errors = this.validate();
return (
<div id="login">
<h1 className="title">Login</h1>
<form action="">
<div
className={
(errors.email && touched.email ? 'has-error' : '') +
' input-holder'
}
>
<Label htmlFor={'loginEmail'}>email</Label>
<input
type="text"
className="input"
id="loginEmail"
value={email}
onChange={this.emailInputChanged}
/>
</div>
<div
className={
(errors.password && touched.password ? 'has-error' : '') +
' input-holder'
}
>
<Label htmlFor={'loginPassword'}>password</Label>
<input
type="password"
className="input"
id="loginPassword"
value={password}
onChange={this.passwordInputChanged}
/>
</div>
<button
type="submit"
className="btn btn-default"
id="loginButton"
onClick={this.loginButtonClicked}
>
login
</button>
</form>
</div>
);
}
}
export function isValidEmail(email) {
const expression = /\S+@\S+/;
return expression.test(String(email).toLowerCase());
}
关于javascript - 验证 render() 中使用的状态变量以设计/填充 html,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57308655/