Taruni
Taruni

Reputation: 211

How to assign object validation in yup for react-select (single-select)

I am trying to implement validation for react-select (single-select) using yup concept. But i am getting this error:

Objects are not valid as a React child (found: object with keys {label, value}). If you meant to render a collection of children, use an array instead.

I want to know how to assign objects in validation schema for yup concept

<Formik
  initialValues={{
    department:"",
  }}
  onSubmit={this.submitForm}
  validationSchema={Yup.object().shape({
    department: Yup.object().shape({
      label: Yup.string().required(),
      value: Yup.string().required(),
    }),
})}>
{ props => {
  const {
    values,
    touched,
    errors,
    isSubmitting,
    handleChange,
    handleBlur,
    handleSubmit,
    selectedOption
  } = props;
  return (
    <React.Fragment>

    <InputLabel shrink htmlFor={'department'}>
    Department</InputLabel>
    <Select
          inputId="department"
          options={options}
          value={values.department}
          onChange={this.onChangeOption}
          onBlur={handleBlur}         
       />
{errors.department && touched.department && ( {errors.department} )} 
Submit </div> </React.Fragment> ); }} 

Upvotes: 20

Views: 57331

Answers (4)

talha
talha

Reputation: 11

For using multiple items in a single object it must be assigned like this

const validationSchema = Yup.object().shape({
  salaryDept: Yup.object().shape({
    employee: Yup.string().required("Field Required"),
    amount: Yup.string().required("Field Required"),
    deduction: Yup.string().required("Field Required"),
      })
 });

in Formik pass validationSchema you just created as follows:

<Formik
  validationSchema={validationSchema}
> </Formik>

and Now the error messages you want to show which is as follows:

helperText={
 errors.salaryDept?.employee &&
 touched.salaryDept?.employee &&
 errors.salaryDept?.employee}
 error={
 errors.salaryDept?.employee &&
 touched.salaryDept?.employee
 }

Upvotes: 1

Mudassir Kidwai
Mudassir Kidwai

Reputation: 57

Little tweak from above comment of Hesters.

    validationSchema={Yup.object().shape({
        valueToBeChange: Yup.object().shape({
           label: Yup.string().required('label is required'),
           value: Yup.string().required('value is required'),
        })
     }

On the front end I have added condition

    (valueToBeChange?.label?.message && valueToBeChange?.label?.message) 
&& (valueToBeChange?.value?.message && valueToBeChange?.value?.message)

Upvotes: 1

Deepak Kadarivel
Deepak Kadarivel

Reputation: 189

You can refine the shape schema with nullable() and required().

Example

const requiredOption = Yup.object()
  .shape({
    value: Yup.string(),
    label: Yup.string(),
  })
  .nullable()
  .required('This field is required.');

Why nullable() and required() to the shape!

  1. If an input is focused and the user decides to skip the input, a value for that input is still set to null and the validation is triggered. Eventually, you would end up with an error like this.

input must be an object type, but the final value was: null. If "null" is intended as an empty value be sure to mark the schema as .nullable()

  1. Instead of having required on individual properties of shape schema, if you are sure all the properties are mandatory, the required function can be called on the object shape directly.

Upvotes: 3

J. Hesters
J. Hesters

Reputation: 14766

I want to know how to assign objects in validation schema for yup concept

You did it correct (as far as I can tell):

validationSchema={Yup.object().shape({
  department: Yup.object().shape({
    label: Yup.string().required(),
    value: Yup.string().required(),
  })
}

What React complains about is this line:

{errors.department && touched.department && ( {errors.department} )} 

What this evalautes to is if errors has a key called department and if touched has a key called department then render the object errors.department. React can't do that. If you want to display the errors you I suggest having a dedicated component (e.g. a <p> tag) for it outside of your select. Something like this:

{errors.department && touched.department && (<p>{errors.department.label}</p>)}

You can do something similar for value.

PS: Your code seems incomplete and poorly formatted (e.g. there is a floating <div /> tag).

Upvotes: 25

Related Questions