From 1416468777e2549dce096331f1f5d2234807d12b Mon Sep 17 00:00:00 2001 From: SebassNoob Date: Thu, 12 Dec 2024 22:43:50 +0900 Subject: [PATCH 1/3] fix: remove forwardref from useImperativeHandle docs --- .../reference/react/useImperativeHandle.md | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index abd93cd4cad..a45b753e3e1 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -23,9 +23,9 @@ useImperativeHandle(ref, createHandle, dependencies?) Call `useImperativeHandle` at the top level of your component to customize the ref handle it exposes: ```js -import { forwardRef, useImperativeHandle } from 'react'; +import { useImperativeHandle } from 'react'; -const MyInput = forwardRef(function MyInput(props, ref) { +function MyInput({ ref, ...props }) { useImperativeHandle(ref, () => { return { // ... your methods ... @@ -38,12 +38,19 @@ const MyInput = forwardRef(function MyInput(props, ref) { #### Parameters {/*parameters*/} -* `ref`: The `ref` you received as the second argument from the [`forwardRef` render function.](/reference/react/forwardRef#render-function) +* `ref`: The `ref` you received as a prop to the `MyInput` component. * `createHandle`: A function that takes no arguments and returns the ref handle you want to expose. That ref handle can have any type. Usually, you will return an object with the methods you want to expose. * **optional** `dependencies`: The list of all reactive values referenced inside of the `createHandle` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If a re-render resulted in a change to some dependency, or if you omitted this argument, your `createHandle` function will re-execute, and the newly created handle will be assigned to the ref. + +In versions prior to React 19, components by default don't expose their DOM nodes to parent components. This was done by opting in with [`forwardRef`](/reference/react/forwardRef) for the parent component to [have access](/learn/manipulating-the-dom-with-refs) to the child's DOM node. + +`forwardRef` is now depreciated. Read the blog on [`ref` as a prop](/blog/2024/12/05/react-19#ref-as-a-prop) to learn more. + + + #### Returns {/*returns*/} `useImperativeHandle` returns `undefined`. @@ -54,22 +61,20 @@ const MyInput = forwardRef(function MyInput(props, ref) { ### Exposing a custom ref handle to the parent component {/*exposing-a-custom-ref-handle-to-the-parent-component*/} -By default, components don't expose their DOM nodes to parent components. For example, if you want the parent component of `MyInput` to [have access](/learn/manipulating-the-dom-with-refs) to the `` DOM node, you have to opt in with [`forwardRef`:](/reference/react/forwardRef) +To expose a DOM node to the parent element, pass in the `ref` prop to the node. -```js {4} -import { forwardRef } from 'react'; - -const MyInput = forwardRef(function MyInput(props, ref) { +```js {2} +function MyInput({ ref, ...props }) { return ; -}); +}; ``` -With the code above, [a ref to `MyInput` will receive the `` DOM node.](/reference/react/forwardRef#exposing-a-dom-node-to-the-parent-component) However, you can expose a custom value instead. To customize the exposed handle, call `useImperativeHandle` at the top level of your component: +With the code above, [a ref to `MyInput` will receive the `` DOM node.](/learn/manipulating-the-dom-with-refs) However, you can expose a custom value instead. To customize the exposed handle, call `useImperativeHandle` at the top level of your component: ```js {4-8} -import { forwardRef, useImperativeHandle } from 'react'; +import { useImperativeHandle } from 'react'; -const MyInput = forwardRef(function MyInput(props, ref) { +function MyInput({ ref, ...props }) { useImperativeHandle(ref, () => { return { // ... your methods ... @@ -77,7 +82,7 @@ const MyInput = forwardRef(function MyInput(props, ref) { }, []); return ; -}); +}; ``` Note that in the code above, the `ref` is no longer forwarded to the ``. @@ -85,9 +90,9 @@ Note that in the code above, the `ref` is no longer forwarded to the ``. For example, suppose you don't want to expose the entire `` DOM node, but you want to expose two of its methods: `focus` and `scrollIntoView`. To do this, keep the real browser DOM in a separate ref. Then use `useImperativeHandle` to expose a handle with only the methods that you want the parent component to call: ```js {7-14} -import { forwardRef, useRef, useImperativeHandle } from 'react'; +import { useRef, useImperativeHandle } from 'react'; -const MyInput = forwardRef(function MyInput(props, ref) { +function MyInput({ ref, ...props }) { const inputRef = useRef(null); useImperativeHandle(ref, () => { @@ -102,7 +107,7 @@ const MyInput = forwardRef(function MyInput(props, ref) { }, []); return ; -}); +}; ``` Now, if the parent component gets a ref to `MyInput`, it will be able to call the `focus` and `scrollIntoView` methods on it. However, it will not have full access to the underlying `` DOM node. @@ -134,9 +139,9 @@ export default function Form() { ``` ```js src/MyInput.js -import { forwardRef, useRef, useImperativeHandle } from 'react'; +import { useRef, useImperativeHandle } from 'react'; -const MyInput = forwardRef(function MyInput(props, ref) { +function MyInput({ ref, ...props }) { const inputRef = useRef(null); useImperativeHandle(ref, () => { @@ -151,7 +156,7 @@ const MyInput = forwardRef(function MyInput(props, ref) { }, []); return ; -}); +}; export default MyInput; ``` @@ -195,11 +200,11 @@ export default function Page() { ``` ```js src/Post.js -import { forwardRef, useRef, useImperativeHandle } from 'react'; +import { useRef, useImperativeHandle } from 'react'; import CommentList from './CommentList.js'; import AddComment from './AddComment.js'; -const Post = forwardRef((props, ref) => { +function Post({ ref, ...props }) { const commentsRef = useRef(null); const addCommentRef = useRef(null); @@ -221,16 +226,16 @@ const Post = forwardRef((props, ref) => { ); -}); +}; export default Post; ``` ```js src/CommentList.js -import { forwardRef, useRef, useImperativeHandle } from 'react'; +import { useRef, useImperativeHandle } from 'react'; -const CommentList = forwardRef(function CommentList(props, ref) { +function CommentList({ ref, ...props }) { const divRef = useRef(null); useImperativeHandle(ref, () => { @@ -252,17 +257,17 @@ const CommentList = forwardRef(function CommentList(props, ref) { {comments} ); -}); +} export default CommentList; ``` ```js src/AddComment.js -import { forwardRef, useRef, useImperativeHandle } from 'react'; +import { useRef, useImperativeHandle } from 'react'; -const AddComment = forwardRef(function AddComment(props, ref) { +function AddComment({ ref, ...props }) { return ; -}); +} export default AddComment; ``` From b60d0a1256e0aabfb53513eabf1512b803d8bdbb Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 16 Dec 2024 16:19:57 +0000 Subject: [PATCH 2/3] Make changes more focused --- .../reference/react/useImperativeHandle.md | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index a45b753e3e1..e8baf188bad 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -25,7 +25,7 @@ Call `useImperativeHandle` at the top level of your component to customize the r ```js import { useImperativeHandle } from 'react'; -function MyInput({ ref, ...props }) { +function MyInput({ ref }) { useImperativeHandle(ref, () => { return { // ... your methods ... @@ -45,9 +45,8 @@ function MyInput({ ref, ...props }) { * **optional** `dependencies`: The list of all reactive values referenced inside of the `createHandle` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If a re-render resulted in a change to some dependency, or if you omitted this argument, your `createHandle` function will re-execute, and the newly created handle will be assigned to the ref. -In versions prior to React 19, components by default don't expose their DOM nodes to parent components. This was done by opting in with [`forwardRef`](/reference/react/forwardRef) for the parent component to [have access](/learn/manipulating-the-dom-with-refs) to the child's DOM node. -`forwardRef` is now depreciated. Read the blog on [`ref` as a prop](/blog/2024/12/05/react-19#ref-as-a-prop) to learn more. +Before React 19, it was necessary to use [`forwardRef`](/reference/react/forwardRef) to get the `ref`. Starting with React 18, [`ref` is available a prop.](/blog/2024/12/05/react-19#ref-as-a-prop) @@ -64,8 +63,8 @@ In versions prior to React 19, components by default don't expose their DOM node To expose a DOM node to the parent element, pass in the `ref` prop to the node. ```js {2} -function MyInput({ ref, ...props }) { - return ; +function MyInput({ ref }) { + return ; }; ``` @@ -74,25 +73,25 @@ With the code above, [a ref to `MyInput` will receive the `` DOM node.](/ ```js {4-8} import { useImperativeHandle } from 'react'; -function MyInput({ ref, ...props }) { +function MyInput({ ref }) { useImperativeHandle(ref, () => { return { // ... your methods ... }; }, []); - return ; + return ; }; ``` -Note that in the code above, the `ref` is no longer forwarded to the ``. +Note that in the code above, the `ref` is no longer passed to the ``. For example, suppose you don't want to expose the entire `` DOM node, but you want to expose two of its methods: `focus` and `scrollIntoView`. To do this, keep the real browser DOM in a separate ref. Then use `useImperativeHandle` to expose a handle with only the methods that you want the parent component to call: ```js {7-14} import { useRef, useImperativeHandle } from 'react'; -function MyInput({ ref, ...props }) { +function MyInput({ ref }) { const inputRef = useRef(null); useImperativeHandle(ref, () => { @@ -106,7 +105,7 @@ function MyInput({ ref, ...props }) { }; }, []); - return ; + return ; }; ``` @@ -204,7 +203,7 @@ import { useRef, useImperativeHandle } from 'react'; import CommentList from './CommentList.js'; import AddComment from './AddComment.js'; -function Post({ ref, ...props }) { +function Post({ ref }) { const commentsRef = useRef(null); const addCommentRef = useRef(null); @@ -235,7 +234,7 @@ export default Post; ```js src/CommentList.js import { useRef, useImperativeHandle } from 'react'; -function CommentList({ ref, ...props }) { +function CommentList({ ref }) { const divRef = useRef(null); useImperativeHandle(ref, () => { @@ -265,7 +264,7 @@ export default CommentList; ```js src/AddComment.js import { useRef, useImperativeHandle } from 'react'; -function AddComment({ ref, ...props }) { +function AddComment({ ref }) { return ; } From 19b6aa437e7b8915b47ff28c7ca49f2c84509987 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 16 Dec 2024 16:21:26 +0000 Subject: [PATCH 3/3] Update useImperativeHandle.md --- src/content/reference/react/useImperativeHandle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index e8baf188bad..92f6e2cdab2 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -46,7 +46,7 @@ function MyInput({ ref }) { -Before React 19, it was necessary to use [`forwardRef`](/reference/react/forwardRef) to get the `ref`. Starting with React 18, [`ref` is available a prop.](/blog/2024/12/05/react-19#ref-as-a-prop) +Starting with React 19, [`ref` is available a prop.](/blog/2024/12/05/react-19#ref-as-a-prop) In React 18 and earlier, it was necessary to get the `ref` from [`forwardRef`.](/reference/react/forwardRef)