useRef

controlled vs uncontrolled element

In principle, we follow the pattern where React manages the state and update the DOM elements on its own. This pattern works with controlled elements, that is, elements on which we plug the value prop that React sees and registers. The pattern is to plug state to the value prop and to request state change in the onChange prop.

Otherwise, DOM elements evolve independently (uncontrolled element): their value doesn't derive from the state, and evolve outside of the React realm, and they do not require nor trigger React re-renders on change. We can set the initial value with defaultValue.

In scenarios where we want to imperatively read or manage an uncontrolled element, we must get a stable reference to it, so that we can read or set its value at arbitrary times using regular DOM APIs. The combination of useRef and ref allows requesting a reference to such an uncontrolled element.

Such reference persists across renders and is only discarded when the component unmounts, which discards the DOM element.

get a reference to an uncontrolled DOM element

In this example, we request a reference to the <input> DOM element, so that keystrokes do not trigger a React re-render.

const myInput = useRef<HTMLInputElement>(null)
// ..
<input ref={myInput}/>

We indicate the element's DOM type as a type parameter. The type can be as broad as HTMLElement, but in this example it is narrowed down to the more accurate HTMLInputElement.

We don't need to indicate null as a type parameter. React already adds it on our behalf.

use the reference

the current property starts as null because there is no way to get a valid DOM reference before the element is mounted (the component has not be painted, the DOM node doesn't exist yet). Later, React assigns the valid DOM reference to current.

myInput.current // the DOM element

// use DOM APIs (not React specific)
if (!myInput.current) return
myInput.current.innerText
myInput.current.innerHTML
myInput.current.value

other uses

We can use useRef to hold any kind of value that persists across renders, and that is only discarded on unmount. For example, we store a counter that increments when the component renders. Because it is not part of the React's state, its incrementation does not trigger a re-render.

earlymorning logo

useRef

controlled vs uncontrolled element

In principle, we follow the pattern where React manages the state and update the DOM elements on its own. This pattern works with controlled elements, that is, elements on which we plug the value prop that React sees and registers. The pattern is to plug state to the value prop and to request state change in the onChange prop.

Otherwise, DOM elements evolve independently (uncontrolled element): their value doesn't derive from the state, and evolve outside of the React realm, and they do not require nor trigger React re-renders on change. We can set the initial value with defaultValue.

In scenarios where we want to imperatively read or manage an uncontrolled element, we must get a stable reference to it, so that we can read or set its value at arbitrary times using regular DOM APIs. The combination of useRef and ref allows requesting a reference to such an uncontrolled element.

Such reference persists across renders and is only discarded when the component unmounts, which discards the DOM element.

get a reference to an uncontrolled DOM element

In this example, we request a reference to the <input> DOM element, so that keystrokes do not trigger a React re-render.

const myInput = useRef<HTMLInputElement>(null)
// ..
<input ref={myInput}/>

We indicate the element's DOM type as a type parameter. The type can be as broad as HTMLElement, but in this example it is narrowed down to the more accurate HTMLInputElement.

We don't need to indicate null as a type parameter. React already adds it on our behalf.

use the reference

the current property starts as null because there is no way to get a valid DOM reference before the element is mounted (the component has not be painted, the DOM node doesn't exist yet). Later, React assigns the valid DOM reference to current.

myInput.current // the DOM element

// use DOM APIs (not React specific)
if (!myInput.current) return
myInput.current.innerText
myInput.current.innerHTML
myInput.current.value

other uses

We can use useRef to hold any kind of value that persists across renders, and that is only discarded on unmount. For example, we store a counter that increments when the component renders. Because it is not part of the React's state, its incrementation does not trigger a re-render.