diff --git a/src/content/learn/manipulating-the-dom-with-refs.md b/src/content/learn/manipulating-the-dom-with-refs.md index a58ffd97c..c1869a631 100644 --- a/src/content/learn/manipulating-the-dom-with-refs.md +++ b/src/content/learn/manipulating-the-dom-with-refs.md @@ -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. -When you put a ref on a built-in component that outputs a browser element like ``, React will set that ref's `current` property to the corresponding DOM node (such as the actual `` 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 ; +} + +function MyForm() { + const inputRef = useRef(null); + return <> +} +``` + +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 ``. Because `` is a [built-in component](/reference/react-dom/components/common) React sets the `.current` property of the ref to the `` DOM element. + +The `inputRef` created in `MyForm` now points to the `` DOM element returned by `MyInput`. A click handler created in `MyForm` can access `inputRef` and call `focus()` to set the focus on ``. ```js import { useRef } from 'react'; -function MyInput(props) { - return ; +function MyInput({ref}) { + return ; } 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', diff --git a/src/content/reference/react/useRef.md b/src/content/reference/react/useRef.md index e40794c38..4d7400fdb 100644 --- a/src/content/reference/react/useRef.md +++ b/src/content/reference/react/useRef.md @@ -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 ; +const MyInput = ({ref}) => { + return ; }; 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. + +--- + +## 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 ; +``` + +You might get an error in the console: + + + +TypeError: Cannot read properties of null + + + +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 ( + + ); +} +``` + +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 ( + + ); +}; + +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)