mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-26 07:25:20 +00:00
example
This commit is contained in:
@@ -1,164 +1,78 @@
|
||||
---
|
||||
title: forwardref
|
||||
title: forwardRef()
|
||||
---
|
||||
|
||||
<Intro>
|
||||
|
||||
`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) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
</Intro>
|
||||
|
||||
- [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 <input {...props} ref={ref} />;});`](#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 <input {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
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} />
|
||||
<button onClick={handleClick}>
|
||||
Focus the input
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
|
||||
//...
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
<Sandpack>
|
||||
|
||||
```js
|
||||
import { forwardRef, useRef } from 'react';
|
||||
```js {3,11}
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
const MyInput = forwardRef((props, ref) => {
|
||||
return <input {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
export default function Form() {
|
||||
const inputRef = useRef(null);
|
||||
|
||||
function handleClick() {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
|
||||
const { label, ...otherProps } = props;
|
||||
return (
|
||||
<>
|
||||
<MyInput ref={inputRef} />
|
||||
<button onClick={handleClick}>
|
||||
Focus the input
|
||||
</button>
|
||||
</>
|
||||
<label>
|
||||
{label}
|
||||
<input {...otherProps} />
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
</Sandpack>
|
||||
|
||||
---
|
||||
You will receive a <CodeStep step={1}>ref</CodeStep> 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.
|
||||
|
||||
<Sandpack>
|
||||
|
||||
```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 <input {...props} ref={realInputRef} />;
|
||||
const { label, ...otherProps } = props;
|
||||
return (
|
||||
<label>
|
||||
{label}
|
||||
<input {...otherProps} ref={ref} />
|
||||
</label>
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
export default function Form() {
|
||||
const inputRef = useRef(null);
|
||||
Now the parent `Form` component can access `MyInput`'s internal <CodeStep step={2}>`<input>` DOM node</CodeStep> 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 (
|
||||
<>
|
||||
<MyInput ref={inputRef} />
|
||||
<button onClick={handleClick}>
|
||||
Focus the input
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
<form>
|
||||
<MyInput label="Enter your name" ref={ref} />
|
||||
<button onClick={handleClick}>Edit</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
</Sandpack>
|
||||
|
||||
---
|
||||
This `Form` component passes a ref to `MyInput`. The `MyInput` component *forwards* that ref to the `<input>` browser tag. As a result, the `Form` component can access the `<input>` 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 <input {...props} ref={ref} />;});` {/*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 <input {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
```
|
||||
#### 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 <input {...props} ref={ref} />;}
|
||||
|
||||
#### Returns {/*returns*/}
|
||||
|
||||
`forwardref` returns a React node.
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user