我使用React创建了以下表单并进行了验证:
这个程序有效,但我有以下问题:
我使用onBlur监视数据检查,但是当用户在第一个字段中输入无效数据以及第一个字段的错误消息(“Only letters”)时,会显示第二个字段的错误消息(“This field is a需要“)。
如何将我的示例改进为:
我的代码:
const ErrorOutput = ({ error }) => <span>{error}</span>
class FormItem extends React.Component {
render() {
return (
<div>
<label>
{this.props.label}
</label>
<input
{...this.props.input}
/>
{this.props.error && <ErrorOutput error={this.props.error} />}
</div>
);
}
}
class App extends React.Component {
constructor(props){
super(props)
this.state = {
firstName: '',
telNo: '',
submit: false,
errors: {
firstName: '',
telNo: '',
},
invalid: false,
}
}
handleSubmit(e){
e.preventDefault()
if (this.validate()) {
console.log('Error!')
} else {
console.log('Success!')
}
}
validate = () => {
const { firstName, telNo } = this.state
const errors = {}
let invalid = false;
if (firstName === '') {
errors.firstName = 'first name is required'
invalid = true;
} else if (!firstName.match(/^[a-zA-Z]+$/)) {
errors.firstName = 'Letters only'
invalid = true;
}
if (telNo === '') {
errors.telNo = 'Phone is required'
invalid = true;
} else if (!telNo.match(/^[0-9]+$/)) {
errors.telNo = 'Numbers only'
invalid = true;
}
this.setState({
invalid,
errors,
})
return invalid;
}
render() {
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<FormItem label='First name:' input={{
type: 'text',
name: 'firstName',
value: this.state.firstName,
onChange: e => this.setState({ firstName: e.target.value }),
onBlur: () => this.validate(),
}} error = {this.state.errors.firstName}
/>
<FormItem label='Phone number:' input={{
type: 'tel',
name: 'telNo',
value: this.state.telNo,
onChange: e => this.setState({ telNo: e.target.value }),
onBlur: () => this.validate(),
}} error = {this.state.errors.telNo}
/>
<button>
Submit
</button>
</form>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<body>
<div id="root"></div>
</body>
答案 0 :(得分:2)
请从修改后的代码中查看我的示例。我试图简化你的逻辑,使其更具可读性和通用性。
const ErrorOutput = ({ error }) => <span> {error} </span>;
const FormItem = ({ label, input, error }) => (
<div>
<label> {label} </label> <input {...input} />
{error && <ErrorOutput error={error} />}
</div>
);
class App extends React.Component {
state = {
firstName: "",
telNo: "",
submit: false,
errors: {}
};
handleSubmit = () => {
const { firstName, telNo, errors } = this.state;
const { firstNameError, telNoError } = errors;
const firstNameIsValid = firstName && !firstNameError;
const telNoIsValid = telNo && !telNoError;
firstNameIsValid && telNoIsValid
? console.log("Success!")
: console.log("Error!");
};
handleInput = event => {
this.setState({
[event.target.name]: event.target.value
});
};
validate = () => {
const { firstName, telNo } = this.state;
let errors = {};
// Name error checking
switch (true) {
case !firstName:
errors.firstNameError = "First name is required";
break;
case !firstName.match(/^[a-zA-Z]+$/):
errors.firstNameError = "First name can have only letters";
break;
case firstName.length <= 2:
errors.firstNameError =
"First name needs to be at least 2 characters long";
break;
default:
errors.firstNameError = "";
break;
}
switch (true) {
case !telNo:
errors.telNoError = "Phone is required";
break;
case !telNo.match(/^[0-9]+$/):
errors.telNoError = "Phone number can have only numbers";
break;
case telNo.length <= 8:
errors.telNoError =
"Telephone number needs to be at least 8 characters long";
break;
default:
errors.telNoError = "";
break;
}
this.setState({
errors
});
};
render() {
const { firstName, telNo, errors } = this.state;
return (
<form>
<FormItem
label="First name:"
input={{
type: "text",
name: "firstName",
value: firstName,
onChange: this.handleInput,
onBlur: this.validate
}}
error={errors.firstNameError}
/>
<FormItem
label="Phone number:"
input={{
type: "tel",
name: "telNo",
value: telNo,
onChange: this.handleInput,
onBlur: this.validate
}}
error={errors.telNoError}
/>
<button type="button" onClick={this.handleSubmit}>
Submit
</button>
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
此外,避免在render方法中使用lambda函数以避免性能瓶颈,因为lambdas会在每次渲染时重新生成,并可能导致其他意外的重新渲染。
答案 1 :(得分:1)
问题是,当发生onBlur事件时,你的valitade方法会尝试验证所有字段。要解决此问题,您可以将事件传递给validate方法,然后仅使用
验证引发事件的字段event.target.name
所以你的验证方法看起来像这样
def loop():
threads = []
for i in range(1,100):
ip = '192.168.0.38'
port = int(i)
t = Thread(target=scan, args=(ip,int(port)))
t.start()
threads.append(t)
[t.join() for t in threads]
并且您的FormItem看起来像
validate = e => {
const { firstName, telNo } = this.state
const errors = {}
let invalid = false
if (e && e.target.name == "firstName") {
if (firstName === "") {
errors.firstName = "first name is required"
invalid = true
} else if (!firstName.match(/^[a-zA-Z]+$/)) {
errors.firstName = "Letters only"
invalid = true
}
}
if(e && e.target.name=="telNo"){
if (telNo === "") {
errors.telNo = "Phone is required"
invalid = true
} else if (!telNo.match(/^[0-9]+$/)) {
errors.telNo = "Numbers only"
invalid = true
}
}
this.setState({
invalid,
errors
})
return invalid
}
答案 2 :(得分:1)
您可能需要考虑使用redux-form来管理整个应用程序的表单状态。即使您不选择使用此库,也值得查看Field
所包含的输入上定义的meta props,以帮助说明在进行时应考虑的因素。验证表格。