React hook form + Yup
Я пытаюсь добиться в своей схеме не совсем валидации, но сообщения для пользователя. Под полем input. У моей схемы есть следующие параметры:
const validationSchema = Yup.object().shape({
title: Yup.string()
.required("Поле обязательно для заполнения")
.max(50, "Заголовок не более 50 символов"),
});
При этом в самом компоненте я получаю кол-во введенных символов:
{...register("title", {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e.target.value.length);
}
})}
Моя задача выводить кол-во оставшихся символов под input пока пользователь не введет >=50 символов. При этом строго к валидации это не относится, т.к. это просто информативное поле. Могу ли я каким-то образом рассчитывать это значение в Yup? Буду благодарен вашим советам. Так как довольно сложно начинать с этой библиотекой!
Ответы (2 шт):
Я не сильно уверен, это ли вам нужно, но вы можете прописать кастомный валидатор:
function validateUsername(value) {
let error;
if (value === 'admin') {
error = 'Nice try!';
}
return error;
}
<Field name="username" validate={validateUsername} />
У вас полагаю это будет выглядеть как то так:
const someValidation = (value) => {
let error
if (value.length < 50) {
error = `Осталось ${50 - value.length} символов`
}
return error
}
<Field validate={someValidation} />
Понимаю, что для ТС уже вряд ли актуально, но может пригодиться тем, кто ищет ответ на тот же вопрос:
Можно использовать функцию yup.test() https://github.com/jquense/yup#schematestname-string-message-string--function--any-test-function-schema
Вообще, функция довольно универсальная, и её можно использовать для самых разных проверок, в том числе с асинхронными вызовами.
Пример:
export const schema = yup.object({
title: yup
.string()
.test('length', (value) => {
// console.log('value:', JSON.stringify(value));
const left = MAX_LENGTH - value.value.length;
if (left >= 0) {
return 'Осталось символов:' + (left);
} else {
return `Не более ${MAX_LENGTH} символов`;
}
}, () => {
return false;
})
.max(MAX_LENGTH, 'Не более 50 символов')
.required('Отсутствует значение'),
});
Но тут есть проблема: если возвращается false, то сообщение об ошибке выводится, но тогда и вся форма становится невалидной. Как при этом и выводить сообщение, и игнорировать ошибку при сабмите - непонятно.
Согласен с Armen, валидатор нужен для валидности, а здесь лучше использовать watch() и span с текстом.