Abdisa Tsegaye
Abdisa Tsegaye

Reputation: 103

React.js onBlur event not being fired when using react-hook-form

react-hook-form works just fine. the problem is when I wanted to attach an onBlur callback on the input field. The onFocus works just fine, but when I take the focus to other input fields or anywhere else, the onBlur event is not fired.

When I removed the register feature from react-hook-form onBlur works just fine, but is not fired when I use register from react-hook-form.

...

"react-hook-form": "^7.41.1",

"react": "^18.2.0"

...

here is the first component in the form

< div className="pb-5">
    < label
        className="block text-sm font-medium mb-1"
        htmlFor="name">
        Name <span className="text-rose-500">*</span>
    < /label>
    <input
        id="name"
        className="form-input w-full ml-2 "
        type="text"
        defaultValue={projectState.project.app.name ?? '-'}
        name="name"
        onFocus={() => {
            console.log('got focus')
        }}
        onBlur={(event) => {
            console.log('lost focus')
        }}
        {...register('name', {
                required: {value: true, message: "Name  is required"},
            },
        )}
    />
    {errors.name && <p className={`ml-2 mt-1 text-red-600`}>
        <span>{errors.name.message}</span>
    </p>}
</div>

I tried to attach a callback to an onBlur event. The event is fired when not using react-hook-form. The onBlur event is not being fired when I am using react-hook-form, only the onFocus is fired

Upvotes: 5

Views: 1179

Answers (2)

raba64577
raba64577

Reputation: 91

This is how I handled mine using a custom react component.

const onBlurHandler = (e) => {
    const inputHighlight = e.target;

    inputHighlight.style.backgroundColor = "#ff40401a";
    inputHighlight.style.borderWidth = "1px";
    inputHighlight.style.borderColor = "#ff4040";
  };

My custom input react component:

<form onSubmit={handleSubmit(onSubmit)}>
<div className="mb-6">
          <ContactInputBox
            type="text"
            name="name"
            id="name"
            placeholder="Your Name"
            onChange={handleChange}
            register={register}
            validationRules={{
              required: "You must enter your name",
              maxLength: {
                value: 200,
                message: "Name must be less than 200 characters",
              },
              onBlur: onBlurHandler // my handler function
            }}
          />
          {errors.name && (
            <div className="text-red-500">{errors.name.message}</div>
          )}
        </div>
<div className="mb-6">
          <ContactInputBox
            type="email"
            name="email"
            id="email"
            placeholder="Your Email"
            onChange={handleChange}
            register={register}
            validationRules={{
              required: "You must enter a valid email",
              pattern: {
                value:
                  /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
                message: "You must enter a valid email",
              },
              maxLength: {
                value: 128,
                message: "Email must be less than 128 characters",
              },
              onBlur: onBlurHandler
            }}
          />
          {errors.email && (
            <div className="text-red-500">{errors.email.message}</div>
          )}
        </div>
</form>

And inside the custom component, I do this:

import React from "react";

const ContactInputBox = ({
  type,
  placeholder,
  name,
  id,
  register,
  validationRules
}) => (
  <>
    <label
      htmlFor={id}
      className="mb-[10px] block capitalize text-base font-medium text-black"
    >
      {name}
    </label>
    <div className="relative">
      <input
        id={id}
        type={type}
        placeholder={placeholder}
        name={name}
        className="w-full bg-[#efe5dc] rounded-md border border-stroke border-black px-[14px] py-3  text-body-color outline-none"
        {...register(name, validationRules)}
      />
    </div>
  </>
);

// Adding a displayName to the component
ContactInputBox.displayName = "ContactInputBox";

export default ContactInputBox;

This works as expected. The onBlur effect will now take effect.

Upvotes: 1

Ahmed Abdelbaset
Ahmed Abdelbaset

Reputation: 4946

register function overrides value, name, onChange, and onBlur props

To add logic to onBlur:


const {onBlur, ...fieldProps} = register('name', {
   required: {value: true, message: "Name  is required"},
})

return (
     // ...
     <input
        id="name"
        className="form-input w-full ml-2 "
        type="text"
        onFocus={() => {
            console.log('got focus')
        }}
        onBlur={(event) => {
            console.log('lost focus')
            onBlur()
        }}
        {...fieldProps}
    />
    // ...
  )

Reference

Upvotes: 5

Related Questions