2

I'm new to using React Hook refs. I followed several code examples, with all of them referencing useRef but the code simply didn't work. Yet when I changed it to createRef then it worked perfectly. I'm thus curious what the difference between the two functions is?

// Near the top of my component
let companyNameRef = React.createRef();

// A useEffect added simply to give focus to a particular input element the first time the component is loaded
useEffect(() => {
  if (companyNameRef.current) {
    companyNameRef.current.focus();
  }
}, [companyNameRef]);

// Within the input element
<Form.Control name='companyName' 
              as='input'
              onChange={e => handleChange(e)}
              ref={companyNameRef}
/>

If I change createRef() to useRef() or useRef(null) or useRef('') the initial focus functionality stops working.

Might anyone know why?

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
robertwerner_sf
  • 1,091
  • 4
  • 21
  • 35

2 Answers2

3

createRef is meant to be used in React class components for capturing DOM handles.
useRef is meant to be used in React function components not only for capturing DOM handles but also as a persistent storage which emulates a class member variable in class components.

In your code (which I assume belongs to React.FunctionComponent) try to set let companyNameRef = useRef(null); and also provide an empty array e.g. [] to useEffect as the second argument to ensure it is called for initial rendering only.

winwiz1
  • 2,906
  • 11
  • 24
  • Just tried what you said but it broke the focus-on-start functionality. Tried all 4 combinations and the only one that works is `createRef` with `companyNameRef` as a dependency. Note: a `console.log` at the top of the `useEffect` proved that `companyNameRef.current` is `null` for some time until it isn't. That's why `[]` as a dependency doesn't work. P.S. My component is indeed a function component: `const AddCustomer = () => { ... }; – robertwerner_sf Sep 16 '19 at 15:48
  • @robertwerner-goodyear My answer has the standard React recipe known to work. If it doesn't then it must be an issue specific to the form you are using. There are several popular forms and you didn't indicate which one you use. The code `as='input'` suggests semantic-ui Form, have a look [here](https://stackoverflow.com/questions/49177857/how-to-autofocus-an-input-field-in-semantic-ui-react) – winwiz1 Sep 16 '19 at 21:35
  • Interesting. FYI I'm using the React Bootstrap Form. In any case, I do appreciate your feedback and helpful hints. Thankfully I do have a straightforward way to get the cursor to appear in the topmost input element upon page load. That it doesn't appear to work with the "standard" approach is interesting but not a deal breaker. – robertwerner_sf Sep 17 '19 at 17:24
1

For detailed explanation of difference between createRef and useRef see What's the difference between `useRef` and `createRef`?

The reason why it stops working in your code when you switch to useRef is

Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.

https://reactjs.org/docs/hooks-reference.html#useref

ckedar
  • 1,859
  • 4
  • 7