Yup.array validate object property is unique with Formik in React.

The requirement is to validate objects in users array has unique name property.

Define a custom method in Yup using Yup.addMethod. Yup.js provides this function to conveniently reuse test functions. Function has to either return true or false to indicate if testing has failed or not respectively, or a new ValidationError created through this.createError().

Yup.addMethod(Yup.array, "unique", function (message, path) {
  return this.test("unique", message, function (list) {
    const mapper = (x) => get(x, path);
    const set = [...new Set(list.map(mapper))];
    const isUnique = list.length === set.length;
    if (isUnique) {
      return true;
    }
    const idx = list.findIndex((l, i) => mapper(l) !== set[i]);
    return this.createError({path: `users[${idx}].${path}`,message});
 });
});

With Yup, we create a Yup formatted object that resembles our intended schema for an object.

const schema = Yup.object().shape({
 users: Yup.array().of(
   Yup.object().shape({
     name: Yup.string().required("Name is required"),        
   })).unique("Duplicate user", "name")
});

Formik has a special config option / prop for Yup object schemas called validationSchema which will automatically transform Yup’s validation errors into a pretty object whose keys match values and touched. Set the validationSchema option to the schema created above.

Use <FieldArray/> that helps with common array/list manipulations. Pass it a name property name=”users”. <FieldArray/> will give access to array helper methods via render props.

Note on line 57, arrayHelpers.push add a value to the end of an array. Similarly, arrayHelpers.remove on line 104 remove an element at an index of an array and return it.

<Field/> hooks up inputs to Formik. Note the name attribute on line 82; it uses to match up with Formik state.

Thank you for reading!

Share