0

I don't understand the underlying behavior of ref system in react hooks.

I understand that useRef will create a constant object where only the current property will change during each render.

I expected createRef to behave the same, but apparently, not:

This code is creating an infinite loop

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0)
  const ref = React.createRef()
  React.useLayoutEffect(() => {setCount(count => count+1)}, [ref])
  return (
    <h1 ref={ref}>{count}</h1>
  );
}

This code is not:

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0)
  const ref = React.useRef()
  React.useLayoutEffect(() => {setCount(count => count+1)}, [ref])
  return (
    <h1 ref={ref}>{count}</h1>
  );
}

So, what is the magic behind createRef?

Moreover, I encountered some cases implying measurement of children, where this behavior is getting really problematic. So what is the point in using createRef over useRef?

Sharcoux
  • 5,546
  • 7
  • 45
  • 78
  • 2
    In a nutshell, `createRef` is for class components, `useRef` for functions. – Robin Zigmond Aug 06 '20 at 22:51
  • I would set this post as duplicate to this [one](https://stackoverflow.com/questions/54620698/whats-the-difference-between-useref-and-createref) – Maxime Helen Aug 06 '20 at 22:57
  • 2
    Does this answer your question? [What's the difference between \`useRef\` and \`createRef\`?](https://stackoverflow.com/questions/54620698/whats-the-difference-between-useref-and-createref) – Maxime Helen Aug 06 '20 at 22:57
  • Actually, I find the answer of @RobinZigmond more accurate to my question. But you can mark it as a duplicate. Thanks – Sharcoux Aug 06 '20 at 23:21

1 Answers1

1

createRef will always create a new ref every time the components renders. Hence you see the createRef is initialised in the constructors of class components or useRef returns a mutable object that persists for the lifetime of component as per the description on official docs:

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

My understanding behind this would be that using functional component implementation using hooks, each render has its own closure so using useRef we are mutating it to be the same on each render. Whereas in class components, the constructor is called only once and hence you have your initialisation done just once.

Pranay Tripathi
  • 1,614
  • 1
  • 16
  • 24
  • 1
    For what I understand, createRef is for class and useRef for functions. But isn't this supposed to figure in a clearer way in the docs? >https://reactjs.org/docs/refs-and-the-dom.html#creating-refs – Sharcoux Aug 06 '20 at 23:19
  • @Sharcoux those docs only talk about class components - they certainly predate Hooks. It's an interesting question why they haven't been updated, or parallel ones written, to use function components with Hooks. But as it is now, Hooks are documented separately, with `useRef` being described [here](https://reactjs.org/docs/hooks-reference.html#useref). I agree it would be nice if it explained clearly how it is different from `createRef` - but the contexts of the two sets of documentation is still clearly different. One is using class components, the other function components with hooks. – Robin Zigmond Aug 07 '20 at 07:33
  • The page I linked mention function components in some parts. I made a PR to update the doc. We will see if it at least starts a discussion to refresh the docs. Until now I was convinced that createRef was the way to creating a ref even in functions. – Sharcoux Aug 07 '20 at 14:52