Answer a question

I'm using Formik with Yup and Typescript, and I have this as an initial value of the form ...

const initialValues = {
    title: "",
    overview: "",
    related_items_id: [],
    short_desc: ""
};

And here's my schema ...

const formSchema = Yup.object().shape({
    title: Yup.string()
        .trim()
        .required("This field is required."),
    overview: Yup.string().required("This field is required."),
    related_items_id: Yup.array()
        .min(1, "Pick at least 1 item")
        .of(Yup.number().required("This field is required.")),
    short_desc: Yup.string().required("This field is required.")
});

Now, I need either the related_items_id array or the short_desc to be required, if one is filled with data the other is not required and vise Versa, how can I accomplish that using something like when in yup?

Here's a codesandbox I created to show the error that I'm getting when trying to use the when method of Yup ...

https://codesandbox.io/s/formik-yup-required-one-or-the-other-nextjs-gujqv

Answers

You can achieve this by creating a type that is interdepedent on related_items_id and short_desc

export interface BaseType {
    title: string;
    overview: string;
}

interface RelatedItemsType extends BaseType {
  related_items_id?: Array<any>;
  short_desc?: never;
}

interface ShortDescType extends BaseType {
  related_items_id?: never;
  short_desc?: string;
}

export type InitialValueType = RelatedItemsType | ShortDescType;

and you can make use of it like this

const initialValues: InitialValueType = {
    title: "",
    overview: "",
    related_items_id: [],
    // short_desc: "" no longer required
};

For conditionally setting your formSchema, checkout the docs Conditionally Set Required Field (Yup).

const basicFormSchema = Yup.object().shape(
    {
      title: Yup.string()
        .trim()
        .required("This field is required."),
      overview: Yup.string().required("This field is required."),
      related_items_id: Yup.array().when("short_desc", {
        is: "",
        then: Yup.array()
          .min(1, "Pick at least 1 item")
          .of(Yup.number().required("This field is required.")),
        otherwise: Yup.array()
      }),
      short_desc: Yup.string().when("related_items_id", {
        is: relatedItemsId => relatedItemsId.length === 0,
        then: Yup.string().required("This field is required."),
        otherwise: Yup.string()
      })
    },
    [["related_items_id", "short_desc"]]
  );
Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐