You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/learn/manipulating-the-dom-with-refs.md
+39-56Lines changed: 39 additions & 56 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -165,27 +165,27 @@ export default function CatFriends() {
165
165
166
166
```css
167
167
div {
168
-
width: 100%;
169
-
overflow: hidden;
168
+
width: 100%;
169
+
overflow: hidden;
170
170
}
171
171
172
172
nav {
173
-
text-align: center;
173
+
text-align: center;
174
174
}
175
175
176
176
button {
177
-
margin: .25rem;
177
+
margin: .25rem;
178
178
}
179
179
180
180
ul,
181
181
li {
182
-
list-style: none;
183
-
white-space: nowrap;
182
+
list-style: none;
183
+
white-space: nowrap;
184
184
}
185
185
186
186
li {
187
-
display: inline;
188
-
padding: 0.5rem;
187
+
display: inline;
188
+
padding: 0.5rem;
189
189
}
190
190
```
191
191
@@ -285,27 +285,27 @@ function setupCatList() {
285
285
286
286
```css
287
287
div {
288
-
width: 100%;
289
-
overflow: hidden;
288
+
width: 100%;
289
+
overflow: hidden;
290
290
}
291
291
292
292
nav {
293
-
text-align: center;
293
+
text-align: center;
294
294
}
295
295
296
296
button {
297
-
margin: .25rem;
297
+
margin: .25rem;
298
298
}
299
299
300
300
ul,
301
301
li {
302
-
list-style: none;
303
-
white-space: nowrap;
302
+
list-style: none;
303
+
white-space: nowrap;
304
304
}
305
305
306
306
li {
307
-
display: inline;
308
-
padding: 0.5rem;
307
+
display: inline;
308
+
padding: 0.5rem;
309
309
}
310
310
```
311
311
@@ -352,15 +352,15 @@ However, if you try to put a ref on **your own** component, like `<MyInput />`,
352
352
```js
353
353
import { useRef } from'react';
354
354
355
-
functionMyInput(props) {
356
-
return<input {...props} />;
355
+
functionMyInput() {
356
+
return<input />;
357
357
}
358
358
359
359
exportdefaultfunctionMyForm() {
360
360
constinputRef=useRef(null);
361
361
362
362
functionhandleClick() {
363
-
inputRef.current.focus();
363
+
inputRef.current?.focus();
364
364
}
365
365
366
366
return (
@@ -376,40 +376,31 @@ export default function MyForm() {
376
376
377
377
</Sandpack>
378
378
379
-
To help you notice the issue, React also prints an error to the console:
380
-
381
-
<ConsoleBlocklevel="error">
382
-
383
-
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
384
-
385
-
</ConsoleBlock>
386
-
387
379
This happens because by default React does not let a component access the DOM nodes of other components. Not even for its own children! This is intentional. Refs are an escape hatch that should be used sparingly. Manually manipulating _another_ component's DOM nodes makes your code even more fragile.
388
380
389
-
Instead, components that _want_ to expose their DOM nodes have to **opt in** to that behavior. A component can specify that it "forwards" its ref to one of its children. Here's how `MyInput` can use the `forwardRef` API:
381
+
Instead, components that _want_ to expose their DOM nodes have to **opt in** to that behavior. A component can specify that it "forwards" its ref to one of its children by passing the `ref` prop down.
390
382
391
383
```js
392
-
constMyInput=forwardRef((props, ref) => {
384
+
functionMyInput({ ref, ...props }) {
393
385
return<input {...props} ref={ref} />;
394
-
});
386
+
}
395
387
```
396
388
397
389
This is how it works:
398
390
399
391
1. `<MyInput ref={inputRef} />` tells React to put the corresponding DOM node into `inputRef.current`. However, it's up to the `MyInput` component to opt into that--by default, it doesn't.
400
-
2. The `MyInput` component is declared using `forwardRef`. **This opts it into receiving the `inputRef` from above as the second `ref` argument** which is declared after `props`.
401
-
3.`MyInput` itself passes the `ref` it received to the `<input>` inside of it.
392
+
2. `MyInput` itself passes the `ref` prop it received to the `<input>` inside of it.
402
393
403
394
Now clicking the button to focus the input works:
404
395
405
396
<Sandpack>
406
397
407
398
```js
408
-
import { forwardRef, useRef } from'react';
399
+
import { useRef } from'react';
409
400
410
-
constMyInput=forwardRef((props, ref) => {
401
+
functionMyInput({ ref, ...props }) {
411
402
return<input {...props} ref={ref} />;
412
-
});
403
+
}
413
404
414
405
exportdefaultfunctionForm() {
415
406
constinputRef=useRef(null);
@@ -442,13 +433,9 @@ In the above example, `MyInput` exposes the original DOM input element. This let
@@ -691,7 +678,7 @@ However, this doesn't mean that you can't do it at all. It requires caution. **Y
691
678
- Refs are a generic concept, but most often you'll use them to hold DOM elements.
692
679
- You instruct React to put a DOM node into `myRef.current` by passing `<div ref={myRef}>`.
693
680
- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements.
694
-
- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using `forwardRef`and passing the second `ref` argument down to a specific node.
681
+
- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using a `ref` prop and passing it down to a specific node.
695
682
- Avoid changing DOM nodes managed by React.
696
683
- If you do modify DOM nodes managed by React, modify parts that React has no reason to update.
697
684
@@ -1093,7 +1080,7 @@ Make it so that clicking the "Search" button puts focus into the field. Note tha
1093
1080
1094
1081
<Hint>
1095
1082
1096
-
You'll need `forwardRef` to opt into exposing a DOM node from your own component like `SearchInput`.
1083
+
You'll need the `ref` prop to opt into exposing a DOM node from your own component like `SearchInput`.
Copy file name to clipboardExpand all lines: src/content/reference/react/useRef.md
+23-31Lines changed: 23 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ import { useRef } from 'react';
28
28
functionMyComponent() {
29
29
constintervalRef=useRef(0);
30
30
constinputRef=useRef(null);
31
-
// ...
31
+
// ...
32
32
```
33
33
34
34
[See more examples below.](#usage)
@@ -65,7 +65,7 @@ import { useRef } from 'react';
65
65
66
66
functionStopwatch() {
67
67
constintervalRef=useRef(0);
68
-
// ...
68
+
// ...
69
69
```
70
70
71
71
`useRef` returns a <CodeStep step={1}>ref object</CodeStep> with a single <CodeStep step={2}>`current` property</CodeStep> initially set to the <CodeStep step={3}>initial value</CodeStep> you provided.
@@ -245,22 +245,22 @@ import { useRef } from 'react';
245
245
246
246
functionMyComponent() {
247
247
constinputRef=useRef(null);
248
-
// ...
248
+
// ...
249
249
```
250
250
251
251
Then pass your ref object as the `ref` attribute to the JSX of the DOM node you want to manipulate:
252
252
253
253
```js [[1, 2, "inputRef"]]
254
254
// ...
255
-
return<input ref={inputRef} />;
255
+
return<input ref={inputRef} />;
256
256
```
257
257
258
258
After React creates the DOM node and puts it on the screen, React will set the <CodeStep step={2}>`current` property</CodeStep> of your ref object to that DOM node. Now you can access the `<input>`'s DOM node and call methods like [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus):
259
259
260
260
```js [[2, 2, "inputRef.current"]]
261
261
functionhandleClick() {
262
-
inputRef.current.focus();
263
-
}
262
+
inputRef.current.focus();
263
+
}
264
264
```
265
265
266
266
React will set the `current` property back to `null` when the node is removed from the screen.
@@ -365,27 +365,27 @@ export default function CatFriends() {
#### Exposing a ref to your own component {/*exposing-a-ref-to-your-own-component*/}
450
450
451
-
Sometimes, you may want to let the parent component manipulate the DOM inside of your component. For example, maybe you're writing a `MyInput` component, but you want the parent to be able to focus the input (which the parent has no access to). You can use a combination of `useRef` to hold the input and [`forwardRef`](/reference/react/forwardRef) to expose it to the parent component. Read a [detailed walkthrough](/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes) here.
451
+
Sometimes, you may want to let the parent component manipulate the DOM inside of your component. For example, maybe you're writing a `MyInput` component, but you want the parent to be able to focus the input (which the parent has no access to). You can use a combination of `useRef` to hold the input and the `ref` prop to expose it to the parent component. Read a [detailed walkthrough](/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes) here.
0 commit comments