我之前有一个受控表单的表单验证,我正在尝试使用钩子将类组件转换为函数组件。但是我在实现原始的onBlur和onChange方法时遇到了问题。我的原始代码:
import React, {Component} from 'react';
import { Label, Button, Col, Row, FormFeedback, Input, Form } from 'reactstrap';
function SignUp (){
return(
<div className="container">
<div className="row" style={{'padding': '30px 12px 60px 12px'}}>
<div className="col col-md-8">
<h4>Inscríbete y crea tu galería de pesonajes!</h4>
</div>
</div>
<div className="row row-content">
<div className="col col-md-8">
{<SignUpForm />}
</div>
</div>
</div>
);
}
class SignUpForm extends Component {
constructor(props){
super(props);
this.state= {
firstName: '',
lastName: '',
email: '',
username: '',
pass: '',
touched:{
firstName: false,
lastName: false,
email: false,
pass: false,
}
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInput = this.handleInput.bind(this);
this.handleBlur = this.handleBlur.bind(this);
}
handleInput (e) {
const target = e.target;
const value = target.type == 'checkbox'? target.checkbox: target.value
const name = target.name;
this.setState({
[name]: value,
})
this.setState({username: this.state.email})
}
handleBlur = (field) => (e) => {
this.setState({
touched : { ...this.state.touched, [field]: true}
})
}
validate (firstName, lastName, email, pass){
const validEmail = (val) => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(val);
const errors = {
firstName: '',
lastName: '',
email: '',
password: ''
}
if (this.state.touched.firstName && firstName.length < 2)
errors.firstName = 'Tu nombre debe tener más de 3 caracteres'
else if (this.state.touched.firstName && firstName.length > 15)
errors.firstName = 'Tu nombre debe tener menos de 15 caracteres'
if (this.state.touched.lastName && lastName.length < 2)
errors.lastName = 'Tu nombre debe tener más de 3 caracteres'
else if (this.state.touched.lastName && lastName.length > 15)
errors.lastName = 'Tu nombre debe tener menos de 15 caracteres'
if (this.state.touched.email && !validEmail(email))
errors.email = 'Email No valido'
else if (this.state.touched.pass && pass.length < 4)
errors.pass = 'Tu password debe tener más de 3 caracteres'
return errors
}
handleSubmit(e) {
//some fetch operation
}
render(){
//const {firstName, lastName, email, pass} = this.state
const errors = this.validate(this.state.firstName, this.state.lastName, this.state.email, this.state.pass)
return(
<Form onSubmit={this.handleSubmit}>
<Row className="form-group">
<Label htmlFor="firstname" md={2}><strong>Tu Nombre</strong></Label>
<Col md={4}>
<Input type="text" id="firstName" name="firstName"
placeholder="Juanito"
value={this.state.firstName}
className="form-control"
valid={errors.firstName === ''}
invalid={errors.firstName !== ''}
onBlur={this.handleBlur('firstName')}
onChange={this.handleInput} />
<FormFeedback>{errors.firstName}</FormFeedback>
</Col>
<Label htmlFor="lastname" md={2}><strong>Tu Apellido</strong></Label>
<Col md={4}>
<Input type="text" id="lastName" name="lastName"
placeholder="Pérez"
value={this.state.lastName}
className="form-control"
valid={errors.lastName === ''}
invalid={errors.lastName !== ''}
onBlur={this.handleBlur('lastName')}
onChange={this.handleInput} />
<FormFeedback>{errors.lastName}</FormFeedback>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="email" md={2}><strong>Email(*)</strong></Label>
<Col md={4}>
<Input type="email" id="email" name="email"
placeholder="juanito@duck.com"
className="form-control"
valid={errors.email === ''}
invalid={errors.email !== ''}
onBlur={this.handleBlur('email')}
onChange={this.handleInput}/>
<FormFeedback>{errors.email}</FormFeedback>
</Col>
<Label htmlFor="password" md={2}><strong>Contraseña</strong></Label>
<Col md={4}>
<Input type="password" id="pass" name="password"
className="form-control"
valid={errors.pass === ''}
invalid={errors.pass !== ''}
onBlur={this.handleBlur('password')}
onChange={this.handleInput} />
<FormFeedback>{errors.pass}</FormFeedback>
</Col>
</Row>
<Row className="form-group">
<Col md={{size:2, offset:10}}>
<Button type="submit" value="submit" name="submit" color="primary">
Inscribirse
</Button>
</Col>
</Row>
</Form>
)
}
}
export default SignUp;
在这里,我尝试实现相同的内容:
import React, { useState } from 'react';
import { Label, Button, Col, Row, FormFeedback, Input, Form } from 'reactstrap';
function SignUp (){
return(
<div className="container">
<div className="row" style={{'padding': '30px 12px 60px 12px'}}>
<div className="col col-md-8">
<h4>Inscríbete y crea tu galería de pesonajes!</h4>
</div>
</div>
<div className="row row-content">
<div className="col col-md-8">
{<SignUpForm />}
</div>
</div>
</div>
);
}
function SignUpForm() {
const [formState, setFormState] = useState({firstName: '', lastName: '', email: '', pass: ''})
const [username, setUsername] = useState('')
const [touched, setTouched] = useState({firstName: false, lastName: false, email: false, pass: false})
function handleInput (e) {
const target = e.target;
const value = target.type == 'checkbox'? target.checkbox: target.value
const name = target.name;
setFormState({ [name]: value })
}
function handleBlur(e) {
console.log(e.target.name)
setTouched({...touched, [e.target.name]: true})
}
function validate(firstName, lastName, email, pass) {
const validEmail = (val) => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(val);
const errors = {
firstName: '',
lastName: '',
email: '',
password: ''
}
if (touched.firstName && firstName.length <= 2)
errors.firstName = 'Tu nombre debe tener más de 2 caracteres'
else if (touched.firstName && firstName.length > 15)
errors.firstName = 'Tu nombre debe tener menos de 15 caracteres'
if (touched.lastName && lastName.length < 2)
errors.lastName = 'Tu apellido debe tener más de 3 caracteres'
else if (touched.lastName && lastName.length > 15)
errors.lastName = 'Tu apellido debe tener menos de 15 caracteres'
if (touched.email && !validEmail(email))
errors.email = 'Email No valido'
else if (touched.pass && pass.length < 4)
errors.pass = 'Tu password debe tener más de 3 caracteres'
return errors
}
function handleSubmit(e) {
//some fetch operation
}
const errors = validate(formState.firstName, formState.lastName, formState.email, formState.pass)
return(
<Form onSubmit={ () => handleSubmit}>
<Row className="form-group">
<Label htmlFor="firstname" md={2}><strong>Tu Nombre</strong></Label>
<Col md={4}>
<Input type="text" id="firstName" name="firstName"
placeholder="Juanito"
value={formState.firstName}
className="form-control"
valid={errors.firstName === ''}
invalid={errors.firstName !== ''}
onBlur={ (e) => handleBlur(e) }
onChange={ (e) => handleInput(e) } />
<FormFeedback>{errors.firstName}</FormFeedback>
</Col>
<Label htmlFor="lastname" md={2}><strong>Tu Apellido</strong></Label>
<Col md={4}>
<Input type="text" id="lastName" name="lastName"
placeholder="Pérez"
value={formState.lastName}
className="form-control"
valid={errors.lastName === ''}
invalid={errors.lastName !== ''}
onBlur={ (e) => handleBlur(e)}
onChange={(e) => handleInput(e)} />
<FormFeedback>{errors.lastName}</FormFeedback>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="email" md={2}><strong>Email(*)</strong></Label>
<Col md={4}>
<Input type="email" id="email" name="email"
placeholder="juanito@duck.com"
value={formState.email}
className="form-control"
valid={errors.email === ''}
invalid={errors.email !== ''}
onBlur={ (e) => handleBlur(e)}
onChange={(e) => handleInput(e)} />
<FormFeedback>{errors.email}</FormFeedback>
</Col>
<Label htmlFor="password" md={2}><strong>Contraseña</strong></Label>
<Col md={4}>
<Input type="password" id="pass" name="password"
value={formState.pass}
className="form-control"
valid={errors.pass === ''}
invalid={errors.pass !== ''}
onBlur={ (e) => handleBlur(e)}
onChange={(e) => handleInput(e)} />
<FormFeedback>{errors.pass}</FormFeedback>
</Col>
</Row>
<Row className="form-group">
<Col md={{size:2, offset:10}}>
<Button type="submit" value="submit" name="submit" color="primary">
Inscribirse
</Button>
</Col>
</Row>
</Form>
)
}
export default SignUp;
当我在第二个字段(姓氏(中乞求输入值时,出现错误,说"名字"未定义(cannot read length property of undefined
(。我认为问题在于setFirstName
无法在验证函数之前设置值,但是在重新排列代码数小时后,我找不到修复它的方法
我也在为此苦苦挣扎,并希望看到它标记为已回答,因为它对我有帮助。
正如@VasylButov指出的,setFormState([name]: value)
覆盖formState对象并将其设置为值。 首先使用展开运算符...formState
,然后修改要setFormState({...formState, [name]: value})
的属性。
作为SO的新贡献者,我不是100%确定发布已经在评论中回答的答案的礼仪是什么,所以如果不正确,请原谅我。