|
| 1 | +--- |
| 2 | +title: useRef Hook |
| 3 | +description: "Details about the useRef React hook in ReScript" |
| 4 | +canonical: "/docs/react/latest/hooks-ref" |
| 5 | +category: "Hooks & State Management" |
| 6 | +--- |
| 7 | + |
| 8 | +# useRef |
| 9 | + |
| 10 | +<Intro> |
| 11 | + |
| 12 | +The `useRef` hooks creates and manages mutable containers inside your React component. |
| 13 | + |
| 14 | +</Intro> |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +<CodeTab labels={["ReScript", "JS Output"]}> |
| 19 | + |
| 20 | +```res |
| 21 | +let refContainer = React.useRef(initialValue); |
| 22 | +``` |
| 23 | + |
| 24 | +```js |
| 25 | + var button = React.useRef(null); |
| 26 | + React.useRef(0); |
| 27 | +``` |
| 28 | + |
| 29 | +</CodeTab> |
| 30 | + |
| 31 | +`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. |
| 32 | + |
| 33 | +Essentially, a `React.ref` is like a "box" that can hold a mutable value in its `.current` record field. |
| 34 | + |
| 35 | +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. |
| 36 | + |
| 37 | +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. |
| 38 | + |
| 39 | +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. |
| 40 | + |
| 41 | + |
| 42 | +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](./refs-and-the-dom#callback-refs) instead. |
| 43 | + |
| 44 | +More infos on direct DOM manipulation can be found in the [Refs and the DOM](./refs-and-the-dom) section. |
| 45 | + |
| 46 | +## Examples |
| 47 | + |
| 48 | +### Managing Focus for a Text Input |
| 49 | + |
| 50 | + |
| 51 | +<CodeTab labels={["ReScript", "JS Output"]}> |
| 52 | + |
| 53 | +```res |
| 54 | +// TextInputWithFocusButton.re |
| 55 | +
|
| 56 | +@bs.send external focus: Dom.element => unit = "focus" |
| 57 | +
|
| 58 | +@react.component |
| 59 | +let make = () => { |
| 60 | + let inputEl = React.useRef(Js.Nullable.null) |
| 61 | +
|
| 62 | + let onClick = _ => { |
| 63 | + inputEl.current |
| 64 | + ->Js.Nullable.toOption |
| 65 | + ->Belt.Option.forEach(input => input->focus) |
| 66 | + } |
| 67 | +
|
| 68 | + <> |
| 69 | + <input ref={ReactDOM.Ref.domRef(inputEl)} type_="text" /> |
| 70 | + <button onClick> {React.string("Focus the input")} </button> |
| 71 | + </> |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +```js |
| 76 | +function TextInputWithFocusButton(Props) { |
| 77 | + var inputEl = React.useRef(null); |
| 78 | + var onClick = function (param) { |
| 79 | + return Belt_Option.forEach(Caml_option.nullable_to_opt(inputEl.current), (function (input) { |
| 80 | + input.focus(); |
| 81 | + |
| 82 | + })); |
| 83 | + }; |
| 84 | + return React.createElement(React.Fragment, undefined, React.createElement("input", { |
| 85 | + ref: inputEl, |
| 86 | + type: "text" |
| 87 | + }), React.createElement("button", { |
| 88 | + onClick: onClick |
| 89 | + }, "Focus the input")); |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +</CodeTab> |
| 94 | + |
| 95 | +### Using a Callback Ref |
| 96 | + |
| 97 | +Reusing the example from our [Refs and the DOM](./refs-and-the-dom#callback-refs) section: |
| 98 | + |
| 99 | +<CodeTab labels={["ReScript", "JS Output"]}> |
| 100 | + |
| 101 | +```res |
| 102 | +// CustomTextInput.re |
| 103 | +
|
| 104 | +@bs.send external focus: Dom.element => unit = "focus" |
| 105 | +
|
| 106 | +@react.component |
| 107 | +let make = () => { |
| 108 | + let textInput = React.useRef(Js.Nullable.null) |
| 109 | + let setTextInputRef = element => { |
| 110 | + textInput.current = element; |
| 111 | + } |
| 112 | +
|
| 113 | + let focusTextInput = _ => { |
| 114 | + textInput.current |
| 115 | + ->Js.Nullable.toOption |
| 116 | + ->Belt.Option.forEach(input => input->focus) |
| 117 | + } |
| 118 | +
|
| 119 | + <div> |
| 120 | + <input type_="text" ref={ReactDOM.Ref.callbackDomRef(setTextInputRef)} /> |
| 121 | + <input |
| 122 | + type_="button" value="Focus the text input" onClick={focusTextInput} |
| 123 | + /> |
| 124 | + </div> |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +```js |
| 129 | +function CustomTextInput(Props) { |
| 130 | + var textInput = React.useRef(null); |
| 131 | + var setTextInputRef = function (element) { |
| 132 | + textInput.current = element; |
| 133 | + |
| 134 | + }; |
| 135 | + var focusTextInput = function (param) { |
| 136 | + return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (input) { |
| 137 | + input.focus(); |
| 138 | + |
| 139 | + })); |
| 140 | + }; |
| 141 | + return React.createElement("div", undefined, React.createElement("input", { |
| 142 | + ref: setTextInputRef, |
| 143 | + type: "text" |
| 144 | + }), React.createElement("input", { |
| 145 | + type: "button", |
| 146 | + value: "Focus the text input", |
| 147 | + onClick: focusTextInput |
| 148 | + })); |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +</CodeTab> |
0 commit comments