diff --git a/beta/src/pages/apis/forwardref.md b/beta/src/pages/apis/forwardref.md index 0bb2ba268..5db66361e 100644 --- a/beta/src/pages/apis/forwardref.md +++ b/beta/src/pages/apis/forwardref.md @@ -1,164 +1,78 @@ --- -title: forwardref +title: forwardRef() --- -`forwardref` forwards the [ref](api/useref) attribute it receives to a child React component. +`forwardRef()` lets your component receive a [ref](/learn/manipulating-the-dom-with-refs) and forward it to a child component. ```js -const MyInputComponent= forwardRef((props, ref) => (return component)); +const SomeComponent = forwardRef((props, ref) => { + // ... +}); ``` -- [Usage](#usage) - - [Forwarding refs to the DOM](#forwarding-refs-to-the-DOM) - - [`forwardref` with useImperativeHandle hook](#forwardref-with-useImperativeHandle-hook) -- [Reference](#reference) - - [`const MyInputComponent = forwardRef((props, ref) => {return ;});`](#forwardref) - --- ## Usage {/*usage*/} -### Forwarding refs to the DOM {/*forwarding-refs-to-the-DOM*/} +### Exposing a DOM node to the parent component {/*exposing-a-dom-node-to-the-parent-component*/} -Call `forwardref` to wrap a component that needs a `ref` to be passed to it by another component. +By default, components don't expose their DOM nodes. To opt in, wrap your component in a `forwardRef` call: -```js - -import { forwardRef, useRef } from 'react'; - -const MyInputComponent = forwardRef((props, ref) => { - return ; -}); - -``` - -The forwardref takes two arguments (props, ref). The second ref argument only exists when you define a component with forwardRef call. This way MyInputComponent can get reference to the underlying button’s DOM node—if necessary. By default, the MyInputComponent component does not opt into using ref. - -```js - -function handleClick() { - inputRef.current.focus(); - } - - return ( - <> - < MyInputComponent ref={inputRef} /> - - - ); - -//... -``` - -Note: Ref forwarding is an opt-in feature that lets some components take a ref they receive, and pass it further down (in other words, “forward” it) to a child. - -Read more about [accessing another component’s DOM nodes](https://beta.reactjs.org/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes) and see examples. - - - -```js -import { forwardRef, useRef } from 'react'; +```js {3,11} +import { forwardRef } from 'react'; const MyInput = forwardRef((props, ref) => { - return ; -}); - -export default function Form() { - const inputRef = useRef(null); - - function handleClick() { - inputRef.current.focus(); - } - + const { label, ...otherProps } = props; return ( - <> - - - + ); -} +}); ``` - ---- +You will receive a ref as the second argument after props. Pass it to the DOM node that you want to expose: -### `forwardref` with useImperativeHandle hook {/*fforwardref-with-useImperativeHandle-hook*/} - -`forwardref` with `useImperativeHandle` hook is another usage for `forwardref`. - -When we use `forwardref` and child component receieves the `ref`from its parent component, there is a possiblity that parent component can manipulate the child components. It would be ideal to limit the exposed functionality to only the ones that are necessary. - -The restriction of exposing functionality to parent components can be achieved by using 'useImperativeHandle' hook. - - - -```js -import { - forwardRef, - useRef, - useImperativeHandle -} from 'react'; +```js {8} [[1, 3, "ref"], [1, 8, "ref", 30]] +import { forwardRef } from 'react'; const MyInput = forwardRef((props, ref) => { - const realInputRef = useRef(null); - useImperativeHandle(ref, () => ({ - // Only expose focus and nothing else - focus() { - realInputRef.current.focus(); - }, - })); - return ; + const { label, ...otherProps } = props; + return ( + + ); }); +``` -export default function Form() { - const inputRef = useRef(null); +Now the parent `Form` component can access `MyInput`'s internal `` DOM node by [passing a ref](/apis/useref#manipulating-the-dom-with-a-ref) to it: + +```js [[1, 2, "ref"], [1, 10, "ref", 30], [2, 5, "ref.current"]] +function Form() { + const ref = useRef(null); function handleClick() { - inputRef.current.focus(); + ref.current.focus(); } return ( - <> - - - - ); +
+ + + + ) } ``` -
---- +This `Form` component passes a ref to `MyInput`. The `MyInput` component *forwards* that ref to the `` browser tag. As a result, the `Form` component can access the `` DOM node and call [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on it. -## Reference {/*reference*/} +Keep in mind that by exposing a ref to the DOM node inside your component, you're making it harder to change your component's internals later. You will typically expose DOM nodes from reusable low-level components like buttons or text inputs, but you won't do it for application-level components like an avatar or a comment. -### `const MyInputComponent = forwardRef((props, ref) => {return ;});` {/*forwardref*/} -Call `forwardref` to wrap a component that needs ref to be passed to it by another component. - -```js -import { forwardRef, useRef } from 'react'; - -const MyInputComponent = forwardRef((props, ref) => { - return ; -}); - -``` -#### Parameters {/*parameters*/} - -`forwardRef` accepts a rendering function as an argument. React will call this function with props and ref as two arguments. - -forwardRef((props, ref) => {return ;} - -#### Returns {/*returns*/} - -`forwardref` returns a React node. diff --git a/beta/src/sidebarReference.json b/beta/src/sidebarReference.json index 25792aa2f..54cd58b5f 100644 --- a/beta/src/sidebarReference.json +++ b/beta/src/sidebarReference.json @@ -15,6 +15,10 @@ "title": "createContext()", "path": "/apis/createcontext" }, + { + "title": "forwardRef()", + "path": "/apis/forwardref" + }, { "title": "useContext()", "path": "/apis/usecontext" @@ -34,10 +38,6 @@ { "title": "useState()", "path": "/apis/usestate" - }, - { - "title": "forwardref", - "path": "/apis/forwardref" } ] },