nothingtodo94
nothingtodo94

Reputation: 3

React hook form with react-select as required field

I'm trying to validate a react-select input field with react-hook-form.(Required input) But I can't seem to do this with the code block below. Can anyone point me in the right direction?

<Controller
   as={Select}
   options={statusOptions}
   name="status"
   control={control}
   className="infoItemDropdown"
   rules={{ required: true }}
   styles={customStyles}
/>

Upvotes: 0

Views: 4342

Answers (3)

You can also use setError and check by clicking on Submit

// ... your code

const {
    control,
    handleSubmit,
    setError,
    formState: { isValid, errors },
  } = useForm<FormValues>({
    mode: 'all'
  })

const onSubmit = (data: FormValues) => {

    if (!data.youSelectName?.value) {
      setError('youSelectName', { message: 'This field is required.' })
      return
    }

   // ... your code
}

return (

// ... your code

 <form onSubmit={handleSubmit(onSubmit)}>
   <Controller
      name='youSelectName'
      control={control}
      render={({ field: { onChange, value } }) => (
         <Select
            onChange={onChange}
            options={options}   
            value={value}
         />
       )}
    />
   {errors.youSelectName && (<div>{errors.youSelectName.message}</div>)}

   <button
       type='submit'
       disabled={!isValid}
    >
     submit
   </button>
 </form>

// ... your code

)

Upvotes: 0

Sebastian Villa
Sebastian Villa

Reputation: 1

You can use these rules to make it required:

rules={{
  validate: (value) => {
    if (typeof value === 'object' && Object.keys(value).length === 0) {
      return 'This field is required.';
    }
    return true;
  },
}}

react-select returns an empty object if no option is selected, so you just need to check for that empty object and return the message.

Upvotes: 0

andres.ara
andres.ara

Reputation: 266

You can wrapper the component react-select:

import Select from 'react-select';
import React, { useState } from 'react';
import PropTypes from 'prop-types';

const RenderSelect = (props) => {
  const {
    field: {
      value,
      onChange,
    },
    data,
  } = props;

  const [selectedOption, setSelectedOption] = useState();
  const handleChange = (e) => {
    onChange(e.value);
    setSelectedOption(e);
  };

  return (
    <Select
      value={selectedOption}
      onChange={handleChange}
      options={data}
    />
  );
};
RenderSelect.propTypes = {
  data: PropTypes.arrayOf(
    PropTypes.shape({
      value: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
      ]).isRequired,
      label: PropTypes.string.isRequired,
    }),
  ).isRequired,
  field: PropTypes.shape({
    value: PropTypes.oneOfType([
      PropTypes.string.isRequired,
      PropTypes.number.isRequired,
    ]),
    onChange: PropTypes.func.isRequired,
  }),
};

RenderSelect.defaultProps = {
  field: { onChange: () => {}, value: '' },
};

export default RenderSelect;

And use it in react hook form:

export default function MyForm() {
  const {
    handleSubmit,
    formState: { isValid },
    control,
  } = useForm({ mode: 'onChange' });

  const onSubmit = (values) =>{
    console.log(values)
  };

  const data = [
    { value: 'chocolate', label: 'Chocolate' },
    { value: 'strawberry', label: 'Strawberry' },
    { value: 'vanilla', label: 'Vanilla' },
  ];
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="select_something"
        control={control}
        rules={{ required: true }}
        render={({ field }) => (<RenderSelect field={field} data={data}/>)
        }
      />
      <button
        disabled={!isValid}
        type="submit"
      >
        Save
      </button>
    </form>
  );
}

This way disable the button submit if the select not has a value.

Upvotes: 1

Related Questions