Почему условная валидация с использованием Zod не функционирует в react-hook-form?

Добрый вечер. Я столкнулся с проблемой валидации данных. У меня есть поле A типа boolean и поле B, которое представляет собой массив. Я хочу, чтобы поле B было обязательным, в том случае если A равно true. 

Я пробовал использовать следующий код: 

<pre><code class="javascript">//schema основные филды
z.object(schema).superRefine((values, ctx) =&gt; {
    if (values.A) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ['B'],
        message: 'Required',
      });
    }
  })

Также 
.and(
  z.union([
    z.object({
      A: z.literal(false),
      B: z.array(z.any()).optional(),
    }),
    z.object({
      A: z.literal(true),
      B: z.array(z.any()),
    }),
  ])
);</code></pre>

Первый вариант не сработал, а второй работает неправильно: всегда требует, чтобы A было false. Как правильно реализовать валидацию для данной логики?
  • 8 декабря 2024 г. 16:13
Ответы на вопрос 1
Доброго вечера! Для решения вашей задачи с условной валидацией, когда обязательность поля B зависит от значения поля A, вы можете использовать метод `refine` или валидацию на уровне объекта с правильной логикой. Я предложу вам пример использования библиотеки Zod с корректной валидацией.

Вот пример, который должен работать так, как вы ожидаете:

```javascript
import { z } from 'zod';

// Определите вашу схему валидации
const schema = z.object({
  A: z.boolean(),
  B: z.array(z.any()).optional(),
}).refine((data) => {
  // Условия: если A true, то B должно быть заполнено
  if (data.A && (!data.B || data.B.length === 0)) {
    return false; // Не проходит валидацию
  }
  return true; // Проходит валидацию
}, {
  message: 'B is required when A is true',
  path: ['B'], // Указывает путь к полю, которое вызывает ошибку
});
```

В этом примере используется метод `refine`, который проверяет, что когда поле A истинно (true), поле B должно быть заполнено. Если оно пустое или не задано, возвращается `false`, что приводит к ошибке валидации.

Затем вы можете использовать эту схему с `react-hook-form`, например:

```javascript
import { useForm, SubmitHandler } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

const MyForm = () => {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
  });

  const onSubmit: SubmitHandler<FormValues> = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label>
        A:
        <input type="checkbox" {...register('A')} />
      </label>
      <label>
        B:
        <input type="text" {...register('B')} />
        {errors.B && <span>{errors.B.message}</span>}
      </label>
      <button type="submit">Submit</button>
    </form>
  );
};
```

В этом коде `react-hook-form` будет использовать схему Zod для валидации ваших данных формы. Если поле A равно true и поле B не заполнено, будет возвращено сообщение об ошибке. 

Обратите внимание, что я предполагаю, что поле B - это массив, и в вашем примере также может использоваться строка или другой тип. Вам нужно будет скорректировать тип данных для поля B в зависимости от ваших нужд.
Похожие вопросы