Javascript-форум (https://javascript.ru/forum/)
-   Библиотеки/Тулкиты/Фреймворки (https://javascript.ru/forum/library-toolkit-framework/)
-   -   Как я могу проверить только одно поле из формы используя Yup? (https://javascript.ru/forum/library-toolkit-framework/84272-kak-ya-mogu-proverit-tolko-odno-pole-iz-formy-ispolzuya-yup.html)

CryNet 26.07.2022 09:36

Как я могу проверить только одно поле из формы используя Yup?
 
Схема выглядит так:

const ValidationScheme = Yup.object().shape({
  email: Yup.string()
    .required('Required')
    .email('Invalid email address'),
  password: Yup.string()
    .required('Required'),
  code: Yup.number()
    .integer()
    .positive()
    .typeError('You must specify a number')
    .required('Required'),
});


При клике на кнопку мне нужно провалидировать только поле "email" из формы. Удалить остальные поля из схемы я не могу, они мне нужны в другой логике (сабмит формы). Как мне это сделать?

P.S это всё работает на Реакте

Nexus 26.07.2022 14:31

Пробовали так?
const emailFieldValidationScheme = Yup.string()
    .required('Required')
    .email('Invalid email address');

const ValidationScheme = Yup.object().shape({
  email: emailFieldValidationScheme,
  password: Yup.string()
    .required('Required'),
  code: Yup.number()
    .integer()
    .positive()
    .typeError('You must specify a number')
    .required('Required'),
});

emailFieldValidationScheme.validateSync('test');

CryNet 26.07.2022 14:35

Цитата:

Сообщение от Nexus (Сообщение 546849)
Пробовали так?

В консоли ошибка, но сам инпут не подсвечивается, мол, он неправильно заполненный:
https://i.ibb.co/T2w9VPX/Screenshot-20220726-143353.png

Nexus 26.07.2022 14:38

CryNet, ну так перехватите эти ошибки и отобразите для пользователя.

CryNet 26.07.2022 16:19

Цитата:

Сообщение от Nexus (Сообщение 546851)
CryNet, ну так перехватите эти ошибки и отобразите для пользователя.

Та у меня есть костыль для этого:
if (rEmail.test(email)) {
      clearErrors('email');
    } else {
      return setError('email', { message: 'Invalid email address' });
    }

Но я бы хотел, чтобы это полностью обработал Yup. Но ваш костыль получше моего.

Nexus 26.07.2022 16:48

Цитата:

Сообщение от CryNet
Но я бы хотел, чтобы это полностью обработал Yup.

Yup только проверяет соответствуют ли передаваемые данные созданной вами схеме, всем остальным, в том числе отображением уведомлений об ошибках, занимается "кто-то другой" (скорее всего, какая-то библиотека для построения форм).

CryNet 26.07.2022 17:02

Цитата:

Сообщение от Nexus (Сообщение 546853)
Yup только проверяет соответствуют ли передаваемые данные созданной вами схеме, всем остальным, в том числе отображением уведомлений об ошибках, занимается "кто-то другой" (скорее всего, какая-то библиотека для построения форм).

Да, правильно. У меня react-hook-form для форм юзается.

const {
    handleSubmit,
    control,
    formState: { errors }, // !important
    setError,
    register,
    clearErrors,
    getValues,
  } = useForm<ILoginForm>({
    resolver: yupResolver(ValidationScheme),
    defaultValues: {
      email: '',
      password: '',
      code: '',
    },
  });

Провозившись с Yum-ом забыл расписать нормально. При клике на Сабмит ошибка из Yum-а попадает в react-hook-form: resolver: yupResolver(ValidationScheme). Видимо таки придётся совместить ваше решение с моим. Я почему-то надеялся, что можно как-то более лаконично решить это. В любом случае -- спасибо вам за идею.

Nexus 26.07.2022 22:29

CryNet, зачем вам понадобилось проверять одно единственное поле на корректность введенных пользователем данных?

Мне кажется, что вы решаете несуществующую проблему, либо существующую, но не тем способом.

CryNet 27.07.2022 09:17

Цитата:

Сообщение от Nexus (Сообщение 546860)
CryNet, зачем вам понадобилось проверять одно единственное поле на корректность введенных пользователем данных?

Мне кажется, что вы решаете несуществующую проблему, либо существующую, но не тем способом.

Сейчас распишу весь флоу. У меня есть форма:
- email
- password
- 2FA
И две кнопки:
- Get 2FA
- Submit
Флоу такой:
- юзер заполнил поля email и password и кликает на кнопку Get 2FA (вот тут мне нужно проверить это единственное поле)
- юзер вводит 2FA и кликает на Сабмит (тут проверяется всё остальное)

Nexus 27.07.2022 18:02

CryNet, я бы сделал как-то так только через class component:

https://codesandbox.io/s/form-exampl...c/LoginForm.js

import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";

export default function LoginForm() {
  const [tokenWasRequested, saveTokenWasRequested] = useState(false);

  const validationScheme = Yup.object().shape({
    email: Yup.string().required("Required").email("Invalid email address"),
    ...(tokenWasRequested
      ? {
          password: Yup.string().required("Required"),
          code: Yup.number()
            .integer()
            .positive()
            .typeError("You must specify a number")
            .required("Required")
        }
      : {})
  });

  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({
    mode: "all",
    criteriaMode: "all",
    resolver: yupResolver(validationScheme)
  });

  const onSubmit = (data) => {
    if (!tokenWasRequested) {
      saveTokenWasRequested(true);

      return;
    }

    console.log(data);
  };

  const fields = [
    {
      type: "email",
      name: "email",
      label: "Email",
      props: {
        readOnly: tokenWasRequested
      }
    }
  ];

  if (tokenWasRequested) {
    fields.push(
      {
        type: "password",
        name: "password",
        label: "Password"
      },
      {
        type: "text",
        name: "code",
        label: "2FA token"
      }
    );
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {fields.map((field) => {
        const errorMessage = errors?.[field.name]?.message;

        return (
          <div
            key={`form-field--${field.type}-${field.name}`}
            className="field-wrapper"
          >
            <input
              {...(field.props ?? {})}
              type={field.type}
              placeholder={field.label}
              className={errorMessage ? "invalid" : undefined}
              {...register(field.name)}
            />
            {errorMessage ? (
              <div className="error-message">{errorMessage}</div>
            ) : null}
          </div>
        );
      })}
      <div className="form-controls">
        <button type="submit">
          {tokenWasRequested ? "Login" : "Get 2FA token"}
        </button>

        {tokenWasRequested ? (
          <button
            type="button"
            onClick={() => {
              saveTokenWasRequested(false);
            }}
          >
            Request another 2FA token
          </button>
        ) : null}
      </div>
    </form>
  );
}


Часовой пояс GMT +3, время: 02:17.