Нативная форма
Для работы с простой формой ( имеется ввиду html тег <form>
) можно использовать следующий подход.
Валидация
Для валидации можно использовать как сторонние библиотеки, так и собственное решение:
- Собственное решение
- Валидация с yup
export function App() {
const emailOptions = {
minLength: {
value: 7,
errorMessage: 'Почта слишком короткая',
},
maxLength: {
value: 30,
errorMessage: 'Почта слишком длинная',
},
minHostLength: {
value: 2,
errorMessage: 'Хост слишком короткий',
},
maxHostLength: {
value: 12,
errorMessage: 'Хост слишком длинный',
},
minDomainLength: {
value: 3,
errorMessage: 'Домен слишком короткий',
},
maxDomainLength: {
value: 6,
errorMessage: 'Домен слишком длинный',
},
minZoneLength: {
value: 2,
errorMessage: 'Доменная зона слишком короткая',
},
maxZoneLength: {
value: 5,
errorMessage: 'Доменная зона слишком длинная',
},
whitelistDomains: {
value: ['plasma.ru', 'gmail.com', 'mail.ru'],
errorMessage: 'Домен не разрешен',
},
blacklistDomains: {
value: ['hah.ah', 'heh.eh'],
errorMessage: 'Домен запрещен',
},
};
const passwordOptions = {
minLength: {
value: 5,
errorMessage: 'Пароль слишком короткий',
},
maxLength: {
value: 20,
errorMessage: 'Пароль слишком длинный',
},
includeUppercase: {
value: true,
errorMessage: 'Пароль должен содержать хотя бы одну заглавную букву',
},
includeLowercase: {
value: true,
errorMessage: 'Пароль должен содержать хотя бы одну строчную букву',
},
includeDigits: {
value: true,
errorMessage: 'Пароль должен содержать хотя бы одну цифру',
},
includeSpecialSymbols: {
value: true,
errorMessage: 'Пароль должен содержать хотя бы один специальный символ',
},
};
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
const [hidden, setHidden] = useState(false);
const handleOnChange = () => {
setEmailError('');
};
const handleOnValidate = ({ errorMessage }: { errorMessage?: string }) => {
setPasswordError(errorMessage || '');
};
const toggleShowPassword = () => setHidden(!hidden);
const HideButton = () => (
<IconButton size="s" view="clear" onClick={toggleShowPassword}>
{hidden ? <IconEyeClosedFill size="xs" color="inherit" /> : <IconEyeFill size="xs" color="inherit" />}
</IconButton>
);
const { handleValidationBlur: handleBlurEmail, handleValidationKeyDown: handleKeyDownEmail } = useValidation({
validationType: 'email',
options: emailOptions,
onValidate: handleOnValidate,
});
const { handleValidationBlur: handleBlurPassword, handleValidationKeyDown: handleKeyDownPassword } = useValidation({
validationType: 'password',
options: passwordOptions,
onValidate: handleOnValidate,
});
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
<TextField
label="Валидация почты"
placeholder="Заполните поле"
validationType="email"
options={emailOptions}
status={emailError ? 'error' : undefined}
helperText={emailError || 'Валидация почты'}
onChange={handleOnChange}
onBlur={handleBlurEmail}
onKeyDown={handleKeyDownEmail}
/>
<TextField
label="Валидация пароля"
placeholder="Заполните поле"
validationType="password"
options={passwordOptions}
status={passwordError ? 'error' : undefined}
helperText={passwordError || 'Валидация пароля'}
onChange={handleOnChange}
onBlur={handleBlurPassword}
onKeyDown={handleKeyDownPassword}
passwordHidden={hidden}
contentLeft={<HideButton />}
/>
</div>
);
}
export function App() {
const schema = yup
.object({
email: yup
.string()
.email("Некорректная почта")
.required("Заполните поле"),
tel: yup
.string()
.required("Заполните поле")
.min(22, "Телефон должен содержать 11 цифр"),
password: yup
.string()
.required("Заполните поле")
.min(8, "Пароль должен быть не менее 8 символов"),
})
.required();
const [errors, setErrors] = useState({});
const onSubmit = async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData.entries());
try {
const validatedData = await schema.validate(data, {
abortEarly: false,
});
console.log(validatedData);
} catch (err) {
const errors = err.inner.reduce((acc, error) => {
return {
...acc,
[error.path]: error.message,
};
}, {});
setErrors(errors);
}
};
const handleChange = (event, name) => {
console.log(name);
setErrors((prevErrors) => ({ ...prevErrors, [name]: "" }));
};
console.log(errors);
return (
<form
onSubmit={onSubmit}
style={{ display: "flex", flexDirection: "column", gap: "20px" }}
>
<TextField
name="email"
placeholder="Почта"
status={errors?.email ? "error" : ""}
helperText={errors?.email}
onChange={(e) => handleChange(e, "email")}
required={false}
/>
<Mask
name="tel"
placeholder="Телефон"
mask="+7 (000) 000 - 00 - 00"
maskChar="_"
view={errors?.tel ? "negative" : "default"}
leftHelper={errors?.tel}
onChange={(e) => handleChange(e, "tel")}
required={false}
/>
<TextField
name="password"
type="password"
placeholder="Пароль"
status={errors?.password ? "error" : ""}
helperText={errors?.password}
onChange={(e) => handleChange(e, "password")}
required={false}
/>
<Button type="submit">Войти</Button>
</form>
);
}