React-select with React-hook-form , focus on error problem

Viewed 1986

I'm trying to validate a form. The problem arises when I insert a React-select component into a controller: even if the rules are set to "required: true", if there is another normal input box error after the Controller, it jumps to the next one and loses focus on the controller error (in this case the "Brand commented section"). Here the code:

export default function Proof() {
    const { register, handleSubmit, errors, control } = useForm();
    const refReactSelect = useRef();

    const createHandler = (data) => {
        console.log(data);
    }
    return (
        <div>
            <form onSubmit={handleSubmit(createHandler)}>
                <label className="font-weight-medium" htmlFor="productCategory">Category</label>
                {/* Name */}
                <div className="form-group pb-2">
                    <label className="font-weight-medium" htmlFor="productName">Name</label>
                    <input
                        className="form-control"
                        type="name"
                        id="productName"
                        name="productName"
                        ref={register({ required: true })}
                    />
                    {errors.productName && errors.productName.type === "required" && (
                        <p className="text-danger">{"Empty name"}</p>
                    )}
                </div>

                <Controller
                    name="productCategory"
                    as={
                        <Select
                            ref={refReactSelect}
                            options={categories}
                            isSearchable={true}
                            placeholder="Select"
                            id="productCategory" />
                    }
                    control={control}
                    rules={{ required: true }}
                />
                {errors.productCategory && errors.productCategory.type === "required" && (
                    <p className="text-danger">{"Empty category"}</p>
                )}

                {/* Brand */}
                <div className="form-group pb-2">
                    <label className="font-weight-medium" htmlFor="productBrand">Brand</label>
                    <input
                        className="form-control"
                        type="text"
                        id="productBrand"
                        name="productBrand"
                        // onChange={(e) => setBrand(e.target.value)}
                        ref={register({ required: true })}
                    />
                    {errors.productBrand && errors.productBrand.type === "required" && (
                        <p className="text-danger">{"Empty Brand"}</p>
                    )}
                </div>

                <div>
                    <button type="submit">Click here </button>
                </div>
            </form>

        </div>
    )
}
1 Answers

I also came across this kind of scenario. So, you can create a function as onError, which will scroll to that field in case of any error.

const onError= () => window.scrollTo(0, inputErrorRef.current?.offsetTop || 0)   

Inside the controller, for onFocus event, you can call this onError function. Also, pass a ref to the error message <p> tag. So whenever we are having an error, the element will be present in dom and we can refer it by ref

 <Controller
  name="productCategory"
   onFocus={onError}
  as={
    <Select
      ref={refReactSelect}
      options={categories}
      isSearchable={true}
      placeholder="Select"
      id="productCategory"
    />
  }
  control={control}
  rules={{ required: true }}
/>;
{
  errors.productCategory && errors.productCategory.type === "required" && (
    <p ref={errorRef} className="text-danger">{"Empty category"}</p>
  );
}

Can you try this once ? and let me know if it helps!

Related