Address Dan's feedback

This commit is contained in:
Matt Carroll
2024-12-17 00:30:35 -08:00
parent b89d0b63fa
commit 649211b51f
2 changed files with 80 additions and 6 deletions

View File

@@ -347,15 +347,32 @@ Read more about [how this helps find bugs](/reference/react/StrictMode#fixing-bu
Refs are an escape hatch that should be used sparingly. Manually manipulating _another_ component's DOM nodes makes your code even more fragile.
</Pitfall>
When you put a ref on a built-in component that outputs a browser element like `<input />`, React will set that ref's `current` property to the corresponding DOM node (such as the actual `<input />` in the browser).
You can pass refs from parent component to child components [just like any other prop](/learn/passing-props-to-a-component).
```js {3-4,9}
import { useRef } from 'react';
function MyInput({ref}) {
return <input ref={ref} />;
}
function MyForm() {
const inputRef = useRef(null);
return <><MyInput ref={inputRef} /></>
}
```
In the above example, a ref is created in the parent component, `MyForm`, and is passed to the child component, `MyInput`. `MyInput` then passes the ref to `<input>`. Because `<input>` is a [built-in component](/reference/react-dom/components/common) React sets the `.current` property of the ref to the `<input>` DOM element.
The `inputRef` created in `MyForm` now points to the `<input>` DOM element returned by `MyInput`. A click handler created in `MyForm` can access `inputRef` and call `focus()` to set the focus on `<input>`.
<Sandpack>
```js
import { useRef } from 'react';
function MyInput(props) {
return <input {...props} />;
function MyInput({ref}) {
return <input ref={ref} />;
}
export default function MyForm() {
@@ -530,7 +547,7 @@ export default function TodoList() {
const newTodo = { id: nextId++, text: text };
flushSync(() => {
setText('');
setTodos([ ...todos, newTodo]);
setTodos([ ...todos, newTodo]);
});
listRef.current.lastChild.scrollIntoView({
behavior: 'smooth',

View File

@@ -455,8 +455,8 @@ Sometimes, you may want to let the parent component manipulate the DOM inside of
```js
import { useRef } from 'react';
const MyInput = (props, ref) => {
return <input {...props} ref={ref} />;
const MyInput = ({ref}) => {
return <input ref={ref} />;
};
export default function Form() {
@@ -535,3 +535,60 @@ function Video() {
Here, the `playerRef` itself is nullable. However, you should be able to convince your type checker that there is no case in which `getPlayer()` returns `null`. Then use `getPlayer()` in your event handlers.
</DeepDive>
---
## Troubleshooting {/*troubleshooting*/}
### I can't get a ref to a custom component {/*i-cant-get-a-ref-to-a-custom-component*/}
If you try to pass a `ref` to your own component like this:
```js
const inputRef = useRef(null);
return <MyInput ref={inputRef} />;
```
You might get an error in the console:
<ConsoleBlock level="error">
TypeError: Cannot read properties of null
</ConsoleBlock>
By default, your own components don't expose refs to the DOM nodes inside them.
To fix this, find the component that you want to get a ref to:
```js
export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}
```
And then add `ref` to the list of props your component accepts and pass `ref` as a prop to the relevent child [built-in component](/reference/react-dom/components/common) like this:
```js {1,6}
const MyInput = ({ value, onChange, ref}) => {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
};
export default MyInput;
```
Then the parent component can get a ref to it.
Read more about [accessing another component's DOM nodes.](/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes)