#reactjs #validation #react-hooks
#reactjs #проверка #реагирующие крючки
Вопрос:
Ссылка на изолированную среду кодаhttps://stackblitz.com/edit/react-cdv6mx?devtoolsheight=33amp;file=src/ResetPassword.js
ОБЪЯСНЕНИЕ: Когда пользователь вводит неверные данные, сервер отправляет ошибку 400: bad request с сообщением, которое можно увидеть на Response tab
вкладке сети. Цель состоит в том, чтобы проверить поля формы перед отправкой формы и отобразить сообщение об ошибке, если введены неправильные поля. Кроме того, предполагается отключить сброс кнопки до тех пор, пока поля формы не будут соответствовать критериям. Таким образом, это предотвратит случайную отправку пользователем наполовину введенных полей.
У меня есть функциональный компонент, в котором у меня есть простая форма.
ПРОБЛЕМА: я вызываю validatForm()
метод onChange
. Метод должен сначала проверить, совпадают ли NewPassword и confirmPassword и соответствуют ли они правилам (требованиям) паролей, и, если true, только после этого отправлять данные.
ОБНОВЛЕННЫЙ КОД НАХОДИТСЯ В ССЫЛКЕ STACKBLITZ ВЫШЕ.
Я использую useFormInput()
, как показано ниже
const email = useFormInput("");
const newPassword = useFormInput("");
const confirmPassword = useFormInput("");
и я написал useFormInput()
метод
const useFormInput = (initialValue) => {
const [value, setValue] = useState(initialValue);
const handleChange = (e) => {
setValue(e.target.value);
};
return {
value,
onChange: handleChange,
};
};
и validateForm()
метод, и я передаю его своему <button/>
/* Your password must contain at least one capital letter, one
*number and one lowercase letter, and it must contain at least 8
*characters*/
const validateForm = (event) => {
let pass = event.target.value;
let reg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;
let test = reg.test(pass);
if (test) {
this.setState({ value: event.target.value });
} else {
alert("password validation unsuccessful. Please try again.");
return;
}
};
и в render()
<FormGroup row>
<Label for="Email" sm={2}>
Email
</Label>
<Col sm={4}>
<Input
type="email"
name="email"
id="Email"
{...email}
/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="newPassword" sm={2}>
New Password
</Label>
<Col sm={4}>
<Input
type="password"
name="password"
id="newPassword"
{...newPassword}
/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="confirmPassword" sm={2}>
Confirm Password
</Label>
<Col sm={4}>
<Input
type="password"
name="confirmPassword"
id="confirmPassword"
{...confirmPassword}
/>
</Col>
</FormGroup>
<div className="form-actions">
{error amp;amp; (
<>
<small style={{ color: "red" }}>{error}</small>
<br />
</>
)}
<br />
<Col lg={{ offset: 2 }} sm={{ size: 1 }}>
<Button
className="mail-reset-btn"
block
type="submit"
value={loading ? "Loading..." : "Login"}
onClick={handleReset}
disabled={!validateForm}
>
Reset
</Button>
</Col>
</div>
</Form>
Комментарии:
1.
this.setState
?2. Вы
disabled={!validateForm}
нажали кнопку отправки,validateForm
не вызывается. Я также не понимаю, почему вы смешали кнопки отправки и сброса.3. для
disabled
: идея состоит в том, чтобы отключить кнопку сброса, если поля формы недопустимы. дляonclick
при сбросе: это ошибка. Я забыл удалить его. Я намерен использоватьonSubmit
4. @SakoBu Извините, я не понимаю. пожалуйста, уточните
5.
ResetPassword
это функциональный компонент, поэтому вызовthis.setState
полностью недопустим. Когда вы пытаетесь проверить поля формы? При отправке?
Ответ №1:
Обновите свой, validateForm
чтобы удалить поля пароля из события формы onSubmit
. Создайте errors
объект для отслеживания ошибок в полях. Если errors
объект пуст, то проверка проходит, в противном случае устанавливается состояние ошибки.
const validateForm = event => {
event.preventDefault();
const { confirmPassword, newPassword } = event.target;
const errors = {};
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;
if (!regex.test(newPassword.value)) {
errors.requirementUnmet = "New password does not meet requirements.";
}
if (newPassword.value !== confirmPassword.value) {
errors.passwordMismatch = "Entered passwords do not match.";
}
if (!Object.keys(errors).length) {
alert("password validation successful.");
setError(null);
return;
}
setError(errors);
};
Прикрепите validateForm
к onSubmit
дескриптору формы.
<Form onSubmit={validateForm}>
Убедитесь, что у вас есть кнопка type =»отправить» в форме.
<Button
className="mail-submit-btn"
block
type="submit"
value={loading ? "Loading..." : "Login"}
>
Submit
</Button>
Обновлен stackblitz (хотя у меня нет учетной записи, поэтому копирую обновленный код ниже.)
Примечание: Я просто JSON.stringify(error)
исправил ошибку для простоты, но вы захотите отобразить это более изящно.
Весь ResetPassword.js
import React, { useState } from "react";
import {
Button,
Form,
FormGroup,
Input,
Col,
Label,
Modal,
ModalHeader,
ModalBody,
ModalFooter
} from "reactstrap";
const useFormInput = initialValue => {
const [value, setValue] = useState(initialValue);
const handleChange = e => {
setValue(e.target.value);
};
return {
value,
onChange: handleChange
};
};
const ResetPassword = props => {
// form inputs
const email = useFormInput("");
const newPassword = useFormInput("");
const confirmPassword = useFormInput("");
// using hooks
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const validateForm = event => {
event.preventDefault();
const { confirmPassword, newPassword } = event.target;
const errors = {};
const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;
if (!regex.test(newPassword.value)) {
errors.requirementUnmet = "New password does not meet requirements.";
}
if (newPassword.value !== confirmPassword.value) {
errors.passwordMismatch = "Entered passwords do not match.";
}
if (!Object.keys(errors).length) {
alert("password validation successful.");
setError(null);
return;
}
setError(errors);
};
const handleReset = e => {
e.preventDefault();
setError(null);
setLoading(true);
// some unrelated redux code
};
return (
<div className="mail-reset" id="forgotPassword">
<div className="mail-reset-content">
<Form onSubmit={validateForm}>
<h3 className="form-title">Enter Information</h3>
<FormGroup row>
<Label for="Email" sm={2}>
Email
</Label>
<Col sm={4}>
<Input
type="email"
name="email"
id="Email"
placeholder="Email"
aria-label="email address"
aria-describedby="email address"
aria-invalid="false"
{...email}
/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="newPassword" sm={2}>
New Password
</Label>
<Col sm={4}>
<Input
type="password"
name="password"
id="newPassword"
placeholder="New Password"
aria-label="new password"
aria-describedby="new password"
aria-invalid="false"
{...newPassword}
/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="confirmPassword" sm={2}>
Confirm Password
</Label>
<Col sm={4}>
<Input
type="password"
name="confirmPassword"
id="confirmPassword"
placeholder="Confirm Password"
aria-label="new password"
aria-describedby="new password"
aria-invalid="false"
{...confirmPassword}
/>
</Col>
</FormGroup>
<div className="modal-wrapper">
<Col sm={{ size: 4, offset: 2 }}>
<Button onClick={toggle} className="passwordReqBtn">
Password Requirements
</Button>
</Col>
<Modal isOpen={modal} toggle={toggle} className="mail-reset-modal">
<ModalHeader toggle={toggle}>Password Requirements</ModalHeader>
<ModalBody>
Your password must contain at least one capital letter, one
number and one lowercase letter, and it must contain at least 8
characters
</ModalBody>
<ModalFooter>
<Button onClick={toggle} className="btn-modal pull-right">
OK
</Button>{" "}
</ModalFooter>
</Modal>
</div>
<div className="form-actions">
{error amp;amp; (
<>
<small style={{ color: "red" }}>{JSON.stringify(error)}</small>
<br />
</>
)}
<br />
<Col lg={{ offset: 2 }} sm={{ size: 1 }}>
<Button
className="mail-reset-btn"
block
type="submit"
value={loading ? "Loading..." : "Login"}
>
Submit
</Button>
<Button
className="mail-reset-btn"
block
type="reset"
value={loading ? "Loading..." : "Login"}
onClick={handleReset}
>
Reset
</Button>
</Col>
</div>
</Form>
</div>
</div>
);
};
export default ResetPassword;
Комментарии:
1. по какой-то причине
form-actions
не выполняется рендеринг. Я прикрепил изображение DOM imgur.com/a/DQoW7Z72. @NaumanTanwir Странно, там должны быть хотя бы
Col
иButton
, верно? Это в вашем stackblitz или на компьютере разработчика на localhost (или другом)?3. @NaumanTanwir Я ничего не менял в своем решении, но в вашем stackblitz
handleReset
есть обработчик onClick для кнопки сброса, и он устраняет ошибки путем вызоваsetError(null);
. Какая ошибка будет / может отображаться при сбросе формы?4. @NaumanTanwir В основном мое мнение, но это ужасная идея. Отправка и сброс — это по сути очень разные действия. Вы просто хотите, чтобы форма сбрасывалась при отправке? Если пользователь частично вводит данные и нажимает эту кнопку, вы сбрасываете форму или отправляете ее? Видите, насколько это запутанно? Только с точки зрения доступности это логистический кошмар.
5. @NaumanTanwir Ранее вы говорили, что хотите, чтобы проверка выполнялась при отправке формы, но это больше похоже на то, что вы хотите, чтобы проверка формы выполнялась при размытии (или изменении) полей. Уже поздно, и я должен идти, но я могу взглянуть на ваш обновленный stackblitz позже.