Home > database >  React ref called multiple times
React ref called multiple times

Time:03-22

Having such simple React (with the react-hook-form library) form

import React, { useRef } from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  const firstNameRef1 = useRef(null);
  const onSubmit = data => { 
    console.log("...onSubmit")
  };
  const { ref, ...rest } = register('firstName', {
    required: " is required!",
    minLength: {
      value: 5,
      message: "min length is <5"
    }
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <hr/>
      <input {...rest} name="firstName" ref={(e) => {
        console.log("...ref")
        ref(e)
        firstNameRef1.current = e // you can still assign to ref
      }} />
      {errors.firstName && <span>This field is required!</span>}

      <button>Submit</button>
    </form>
  );
}

I'm getting:

...ref 
...ref 
...onSubmit 
...ref 
...ref 

in the console output after the Submit button click.

My question is why is there so many ...ref re-calls? Should't it just be the one and only ref call at all?

P.S. When I've removed the formState: { errors } from the useForm destructuring line above the problem disappears - I'm getting only one ...ref in the console output as expected.

CodePudding user response:

It is happening because you are calling ref(e) in your input tag. That's why it is calling it repeatedly. Try removing if from the function and then try again.

<input {...rest} name="firstName" ref={(e) => {
  console.log("...ref")
  ref(e)  // <-- ****Remove this line of code*****
  firstNameRef1.current = e // you can still assign to ref
}} />

CodePudding user response:

My question is why is there so many ...ref re-calls?

This is happening because every time you render, you are creating a new function and passing it into the ref. It may have the same text as the previous function, but it's a new function. React sees this, assumes something has changed, and so calls your new function with the element.

Most of the time, getting ref callbacks on every render makes little difference. Ref callbacks tend to be pretty light-weight, just assigning to a variable. So unless it's causing you problems, i'd just leave it. But if you do need to reduce the callbacks, you can use a memoized function:

const example = useCallback((e) => {
  console.log("...ref")
  ref(e);
  firstNameRef1.current = e
}, [])

// ...
<input {...rest} name="firstName" ref={example} />
  • Related