Logo

dev-resources.site

for different kinds of informations.

Complete useRef() hook with live code examples

Published at
3/5/2020
Categories
typescript
react
useref
hooks
Author
danielpdev
Categories
4 categories in total
typescript
open
react
open
useref
open
hooks
open
Author
10 person written this
danielpdev
open
Complete useRef() hook with live code examples

What's up with useRef hook?

useRef returns an object with a current property. This current property gets the initial value of the argument passed to useRef hook. The reference to {current: <any value>} object will persist from render to render.

Is useRef hook used only for accessing Document Object Model(DOM) elements?

No, useRef hook can also be used as an instance variable.

How can useRef be used as an instance variable?

The object returned by the useRef hook can be used as a container whose current property can store a value over the lifetime of the functional component.

The most common use case of useRef hook is:

  • Keep a live ref to a DOMElement.
  function TextInput() {
    const inputEl = useRef(null);
    return (
      <>
        <input ref={inputEl} type="text" />
      </>
    );
  }

The important thing here is:

      const inputEl = useRef(null);

and

        <input ref={inputEl} type="text" />

After the first render, inputEl will have an object with current property pointing to our input element.

Difference between using useRef and assigning an ordinary {current: ...} object

Live example

As of React documentation, useRef gives us the same object on every render while plain old JS object will just be recreated every render.

1. With useRef


  function setWindowRef<T>(ref: React.RefObject<T>) {
    (window as any).ref = ref;
  }

  function getWindowRef<T>() {
    return (window as any).ref;
  }

  export default function UseRefReact() {
    const [renders, setValue] = React.useState(1);
    const ref = React.useRef(null);

    React.useEffect(() => {
      setWindowRef<HTMLDivElement>(ref);
    });

    return (
      <div className="UseRefReact">
        <div>UseRef with React.useRef(null)</div>
        <button onClick={e => setValue(renders + 1)}> Rerender </button>
        <div ref={ref}>Renders {renders}</div>
        <div>
          {" "}
          {getWindowRef() === ref ? "same ref object" : "ref not set yet"}{" "}
        </div>
      </div>
    );
  }

Making use of const ref = React.useRef(null); and <div ref={ref}>Renders {renders}</div> will give
us the reference to that div element.

How can we check if the object ref was changed when our functional component was rendered ?

Another object persisting between renders will help us check if the ref object has changed.

window object enters the scene:

  function setWindowRef<T>(ref: React.RefObject<T>) {
    (window as any).ref = ref;
  }

  function getWindowRef<T>() {
    return (window as any).ref;
  }

Ok, now that our helper functions are defined, we can move to the next step:

When do we call our functions?

  • call setWindowRef after our component has been rendered

      setTimeout(() => {
        setWindowRef<HTMLDivElement>(ref);
      });
    
  • getWindowRef when the view is rendered

    <div>
        {getWindowRef() === ref ? "same ref object" : "ref not set yet"}
     </div>  

First render we will get "ref not set yet".

Why?

Long answer:

  • The reason we get "ref not set yet" on first render is because of how JS works under the hood.

Short answer:

  • setTimeout(() => { setWindowRef<HTMLDivElement>(ref); }); setWindowRef will be queued and executed after we return from our function.

On any other renderers we will get "same ref object", meaning that indeed React makes sure that we get the same instance with every render.(Thanks React).

2. Without useRef

function setWindowObjectRef<T>(ref: React.RefObject<T>) {
  (window as any).objectRef = ref;
}

function getWindowRef<T>() {
  return (window as any).objectRef;
}
export default function UseRefObject() {
  const [renders, setValue] = React.useState(1);
  const ref = { current: null };

  setTimeout(() => {
    setWindowObjectRef<HTMLDivElement>(ref);
  });
  return (
    <div className="UseRefObject">
      <div>UseRef with {`{ current: null }`}</div>
      <button onClick={e => setValue(renders + 1)}> Rerender </button>
      <div ref={ref}>Renders {renders}</div>
      <div>
        {" "}
        {getWindowRef() === ref ? "same ref object" : "ref object changed"}{" "}
      </div>
    </div>
  );
}

Examples are pretty much the same.

Small differences:

  • window.objectRef instead of window.ref because we don't what to mess up our example
  • const ref = { current: null }; instead of using React.useRef(null)

Now, on every render we get "ref object changed" and it seems that we verified how useRef() works and why we should use it when we want to persist a value between renders.

Conclusion:

  • useRef will always return the same object with the same current property value pointing to the same object throughout the lifetime of your functional component.

  • even though useRef creates a plain JS object with a current property, manually creating an object like
    { current: null }to select a DOM element by passing it to a ref attribute, will not persist the object between renders.

Article first posted on danielpdev.io

Follow me on twitter

useref Article's
29 articles in total
Favicon
How to create components interfaces using useRef/forwardRef/useImperativeHandle
Favicon
Hooks Behind The Scenes 3, UseRef!!!
Favicon
Mastering React's useRef Hook: Working with DOM and Mutable Values
Favicon
Understanding useRef: A Beginners Guide
Favicon
useRef Hook Explained
Favicon
useRef() in React . . .
Favicon
React State Management: When & Where add your states?
Favicon
Unlocking the Power of useRef: Besic to Advanced Examples for React Developers
Favicon
Leveraging useRef in TypeScript for Efficient DOM Manipulation
Favicon
Unlocking the Power of React Hooks
Favicon
React.useRefの理解を含めるエクササイズ
Favicon
Mastering React's useRef Hook: A Deep Dive
Favicon
Unlocking the Power of useRef in React: 12 Essential Use Cases
Favicon
Série React Hooks: useRef
Favicon
Toggle Password Visibility Using React useRef
Favicon
Stop using useState for everything
Favicon
Using React hooks to develop a Video Player
Favicon
React - How to load a form with the latest data
Favicon
React: сфокусировать поле ввода по чекбоксу
Favicon
How do I check/uncheck all checkboxes with a button In React Js using useRef() Hook ?
Favicon
Multiple item using one ref
Favicon
Closures and useEffects
Favicon
I need help. TypeError: Cannot read properties of undefined (reading 'current')
Favicon
Using React useRef Hook to access immediate past props or state.
Favicon
Compare Props in React Functional Components.
Favicon
Creating infinitely scrolling SPA using React
Favicon
useRef()가 순수 자바스크립트 객체라는 의미를 곱씹어보기
Favicon
Complete useRef() hook with live code examples
Favicon
Useful Patterns with React hooks

Featured ones: