DEV Community

Linas Spukas
Linas Spukas

Posted on

Manipulating DOM Elements With React Hook useRef()

It is usually advised to avoid using refs in React for anything that can be done declaratively, but there are few cases when you need to imperatively modify DOM element. One of it, to access or modify a child outside of the typical dataflow, like managing focus, selecting text or media playback.

How To

Ref attributes may not be used on function components because they don't have instances, but React Hooks introduced a function useRef(), which holds and returns a mutable object .current.

The function takes the optional initial value as an argument, and if you forgot to pass it, don't worry, you will be able to do it later.

const refContainer = useRef(initialValue);

And the returned mutable object exists through the whole lifetime of the component

The best ilustration how useRef() works would be with the example of input field manipulation:

function App() {
    const inputRef = React.useRef();

    return (
        <>
            <input ref={inputRef} />
            <button onClick={() => inputRef.current.focus()} />
        </>
    )
}

The inputRef holds the reference to the DOM element input, and all properties of the element can be accessed directly through the inputRef.current. As a side effect of clicking the button, we can manipulate the input, like setting it on focus inputRef.current.focus().

Not only for DOM

As the hook holds a mutable object, we can use it not only for accessing the DOM elements, but to hold any value: strings, numbers, other objects, functions. You can store previous state values inside it in case you need to access it later.

The example below demonstrates how the number value is stored inside the mutable object, and on every component render it updates, increments and renders the count to the browser. Now you will know how many times your component was re-rendered unnecessarily :)

function App() {
    const ref = React.useRef(0);
    React.useEffect(() => {
        ref.current += 1;
    });

    return (
        <div>{ref.current}</div>
    )
}

Also, need to keep in mind, that changes to the mutable object .current does not notify you, so the component will not re-render when you modify the object.

Final notes

useRef() creates a simple JavaScript object, I think it's a great hook for holding and accessing not only refs but any data like we do it with the fields of the class components.

Top comments (0)