0

I'm trying to use refs created from an array but when I check in the Component tab of the React Developper Tools, ref passed to the input are always undefined. Something I missed here?

const MyComponent = () => {
  const refs = useMemo(() => Array(2).fill(0).map(i => React.createRef()), []);

  const TextInput = ({ name, value, inputRef }) => (
    <input
      name={name}
      value={value}
      onChange={updateField()}
      ref={inputRef}
    />
  )

  return (
    <TextInput
      name="lastname"
      value="Nom *"
      inputRef={refs[0]}
    />
    <TextInput
      name="firstname"
      label="Prénom *"
      inputRef={refs[1]}
    />
  )
}

Thanks!

6
  • What's the value of i in refs[i]? Commented Sep 17, 2021 at 9:57
  • Sorry @JayendraSharan , I don't use i anymore. I updated my sample code. Commented Sep 17, 2021 at 10:04
  • What are you attempting to do here? Why not just use two useRefs? Commented Sep 17, 2021 at 10:05
  • @AKX I could if I always had a fixed number of TextInput components. But it can occur that the number of components vary and I have to generate refs dynamically in that case. Commented Sep 17, 2021 at 10:08
  • That will be easiest done with a function-style ref instead. Commented Sep 17, 2021 at 10:11

1 Answer 1

1

If you have a variable number of refs, you'll want a function-style ref instead, like below.

const TextInput = ({
  name,
  value,
  refs
}) => (
  <input
    name={name}
    value={value}
    ref={(el) => {
      refs.current[name] = el;
    }}
  />
);

const MyComponent = () => {
  const refs = React.useRef({});

  React.useLayoutEffect(() => {
    console.log(refs.current);
  }, []);

  return (
    <>
      <TextInput name="lastname" value="Nom *" refs={refs} />
      <TextInput name="firstname" value="Prénom *" refs={refs} />
    </>
  );
};

This will log

{lastname: HTMLInputElement, firstname: HTMLInputElement}

As an aside: never nest components – that will cause unnecessary rerenders.

Sign up to request clarification or add additional context in comments.

4 Comments

It doesn't work as I'd like. First, I don't see both refs logged, just the initial value {}. And in my actual code, I try to focus() on refs.current[name], but only one input can be edited at one point(because of unique ref in the refs obj). I would like to focus on both input at the same time. I guess it would work if I'd had the two ref originally created as shown in your "log".
Only one element can have focus at any given time. You can't have two simultaneously focus()ed elements.
You're right, sorry for my confused comment. It's just that when the first input has focus, I have to click twice on the second one to set focus on it.
The focus problem was not related to your pattern. It works now. Thanks, I did know I could pass a callback as ref.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.