Я создал следующую форму с проверкой с использованием React:
- данные должны быть проверены во время ввода
- данные должны быть проверены еще раз перед отправкой
- все данные все поля обязательны для заполнения и данные действительны
Эта программа работает, но у меня возникает следующая проблема:
Я проверяю проверку данных с помощью onBlur, но когда пользователь вводит недопустимыйданные в первом поле вместе с сообщением об ошибке для первого поля («Только буквы»), сообщение об ошибке отображается для второго поля («Это поле является обязательным»).
Как можно улучшитьЭто мой пример:
- во время ввода - сообщение об ошибке («Это поле обязательно для заполнения» или конкретное сообщение для недопустимых данных) отображалось только в том случае, если пользователь коснулся определенного поля
- если была нажата кнопка «Отправить» - тогда сообщения об ошибках должны отображаться рядом со всеми полями с неверными данными
Мой код:
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>