Docs / ReasonReact / HooksRef

useRef

The useRef hooks creates and manages mutable containers inside your React component.

Usage

ReScriptJS Output
 
let refContainer = React.useRef(initialValue);

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

Essentially, a React.ref is like a "box" that can hold a mutable value in its .current record field.

You might be familiar with refs primarily as a way to access the DOM. If you pass a ref object to React with <div ref={ReactDOM.Ref.domRef(myRef)} />, React will set its .current property to the corresponding DOM node whenever that node changes.

However, useRef() is useful for more than the ref attribute. It's handy for keeping any mutable value around similar to how you’d use instance fields in classes.

This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render.

Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current record field 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.

More infos on direct DOM manipulation can be found in the Refs and the DOM section.

Examples

Managing Focus for a Text Input

ReScriptJS Output
 
// TextInputWithFocusButton.re

@bs.send external focus: Dom.element => unit = "focus"

@react.component
let make = () => {
  let inputEl = React.useRef(Js.Nullable.null)

  let onClick = _ => {
    inputEl.current
    ->Js.Nullable.toOption
    ->Belt.Option.forEach(input => input->focus)
  }

  <>
    <input ref={ReactDOM.Ref.domRef(inputEl)} type_="text" />
    <button onClick> {React.string("Focus the input")} </button>
  </>
}

Using a Callback Ref

Reusing the example from our Refs and the DOM section:

ReScriptJS Output
 
// CustomTextInput.re

@bs.send external focus: Dom.element => unit = "focus"

@react.component
let make = () => {
  let textInput = React.useRef(Js.Nullable.null)
  let setTextInputRef = element => {
    textInput.current = element;
  }

  let focusTextInput = _ => {
    textInput.current
    ->Js.Nullable.toOption
    ->Belt.Option.forEach(input => input->focus)
  }

  <div>
    <input type_="text" ref={ReactDOM.Ref.callbackDomRef(setTextInputRef)} />
    <input
      type_="button" value="Focus the text input" onClick={focusTextInput}
    />
  </div>
}