Formik + yup: как проверить схему местоположения, где поля (страна, штат, город) не являются обязательными, но если одно из них заполнено, каждое должно быть заполнено?

У меня есть схема ниже

validationSchema={yup.object().shape({
  firstName: yup
    .string()
    .required("Name cannot be empty")
    .matches(NAME_REGEX, "Name can only contain english characters"),
  lastName: yup
    .string()
    .required("Name cannot be empty")
    .matches(NAME_REGEX, "Name can only contain english characters"),
  location: yup
    .object()
    .nullable()
    .shape({
      country: yup.string().required(),
      state: yup.string().required(),
      city: yup.string().required()
    })
})}

Проверка для firstName и lastName работает нормально, но я не знаю, как проверить location.
Требование: location вообще не требуется для заполнения. Но если какое-либо поле (_6 _ / _ 7 _, _ 8_) заполнено, то должны быть заполнены все три поля. Либо все, либо ничего.

Хотя я пытался проверить это, как указано выше, но это не работает.

Другое требование проверки: эти значения выбираются из элемента select html, из которых первым <option> является <option key={0}>-select-</option>. Поэтому я не хочу, чтобы мои пользователи также выбирали эту опцию. На данный момент я обрабатываю это в onSubmit, проверяя значения, и если они содержат -select-, то эти значения не будут учитываться и будут заменены существующими.

обновление:
location никогда не может быть нулевым. Если пользователь не установил какое-либо поле местоположения, тогда также location будет:

location: {
   country: null,
   state: null,
   city: null
}

location никогда не может быть нулевым, могут быть только его свойства.

Как мне сделать эти проверки?


person TheCoder    schedule 04.05.2019    source источник


Ответы (1)


Вы должны установить для location по умолчанию значение null с помощью mixed.default (value) нравится:

location: yup
    .object()
    .default(null)
    .nullable()
    .shape({
      country: yup.string().required(),
      state: yup.string().required(),
      city: yup.string().required()
    })

Обновление:

location никогда не может быть нулевым, могут быть только его свойства.

Сделать это можно так:

location: object()
    .shape({
      country: string().default(null).nullable().test(
        value => value === null || value,
      ),
      state: string().default(null).nullable().test(
        value => value === null || value,
      ),
      city: string().default(null).nullable().test(
        value => value === null || value,
      )
    })
person Fraction    schedule 04.05.2019
comment
Не работает. Если я редактирую firstname или lastName, я получаю ошибку (от formik) location.country must be a string type, but the final value was: null. If "null" is intended as an empty value be sure to mark the schema as .nullable(). Я даже не трогал ни один элемент select - person TheCoder; 04.05.2019
comment
Объект location. Он может быть нулевым, но если пользователь попытался передать ему некоторые значения (страна / штат / город), он должен передать все три. Но с этой конфигурацией, даже если я редактирую firstName, да, проверяет location.country. Почему он попадает внутрь location? Он должен входить в location только в случае изменения страны / штата / города. - person TheCoder; 04.05.2019
comment
Я не знаю, в чем проблема, вы можете предоставить кодовый ящик? и взгляните на runkit.com/fraction01/5ccd994faa364f001aaed845, проверка прошла успешно - person Fraction; 04.05.2019
comment
Думаю, я знаю, в чем проблема. Пожалуйста, смотрите обновление. - person TheCoder; 04.05.2019