forwardRef

`forwardRef` 是 React 提供的一种高级 API,用于在函数组件中转发(forward)`ref` 到子组件的 DOM 元素或类组件。这对于需要直接操作子组件的 DOM 节点或获取子组件实例的情况非常有用。

如何使用`forwardRef`

示例

假设我们有一个自定义的输入框组件 `FancyInput`,我们希望通过父组件能够直接访问这个输入框的 DOM 节点,以便在父组件中调用焦点(focus)等方法。

**1. 创建 `FancyInput` 组件,使用 `React.forwardRef`**

```javascript

import React, { forwardRef } from 'react';

const FancyInput = forwardRef((props, ref) => (

<input ref={ref} type="text" className="fancy-input" {...props} />

));

export default FancyInput;

```

在这个例子中,我们使用 `React.forwardRef` 创建了一个函数组件 `FancyInput`。这个组件接收 `props` 和 `ref` 作为参数,并将 `ref` 转发给内部的 `input` 元素。

**2. 在父组件中使用 `FancyInput` 并直接操作其 DOM 节点**

```javascript

import React, { useRef } from 'react';

import FancyInput from './FancyInput';

function App() {

const inputRef = useRef(null);

const handleClick = () => {

if (inputRef.current) {

inputRef.current.focus();

}

};

return (

<div>

<h1>Forward Ref Example</h1>

<FancyInput ref={inputRef} />

<button onClick={handleClick}>Focus the input</button>

</div>

);

}

export default App;

```

在这个例子中,使用 `useRef` 钩子创建了一个 `ref`,然后将这个 `ref` 传递给 `FancyInput` 组件。调用 `handleClick` 函数时,通过 `ref` 获取到 `FancyInput` 内部的 `input` 元素并使其获得焦点。

组合 `forwardRef` 和 `useImperativeHandle`

有时你可能希望在转发 `ref` 的同时自定义暴露给父组件的实例值。你可以使用 `useImperativeHandle` 钩子来实现这一目的。

示例

**修改 `FancyInput` 组件**

```javascript

import React, { forwardRef, useImperativeHandle, useRef } from 'react';

const FancyInput = forwardRef((props, ref) => {

const inputRef = useRef();

useImperativeHandle(ref, () => ({

focus: () => {

inputRef.current.focus();

},

clear: () => {

inputRef.current.value = '';

}

}));

return <input ref={inputRef} type="text" className="fancy-input" {...props} />;

});

export default FancyInput;

```

在这个例子中,我们使用了 `useImperativeHandle` 钩子来自定义暴露给父组件的实例值。现在父组件可以调用 `focus` 和 `clear` 方法。

**在父组件中使用自定义方法**

```javascript

import React, { useRef } from 'react';

import FancyInput from './FancyInput';

function App() {

const inputRef = useRef(null);

const handleFocus = () => {

if (inputRef.current) {

inputRef.current.focus();

}

};

const handleClear = () => {

if (inputRef.current) {

inputRef.current.clear();

}

};

return (

<div>

<h1>Forward Ref with useImperativeHandle</h1>

<FancyInput ref={inputRef} />

<button onClick={handleFocus}>Focus the input</button>

<button onClick={handleClear}>Clear the input</button>

</div>

);

}

export default App;

```

在这个父组件中,我们可以使用 `ref` 调用 `FancyInput` 组件中定义的 `focus` 和 `clear` 方法。

总结

  • **`forwardRef`**:允许你在函数组件中转发 `ref` ,使得父组件能够访问子组件的 DOM 节点或实例。

  • **`useImperativeHandle`**:配合 `forwardRef` 使用,允许你自定义暴露给父组件的实例值,可以使 `ref` 除了能访问 DOM 节点之外还可以调用自定义方法。

通过这些高级 API ,我们可以在函数组件中灵活地操作子组件的 DOM 节点或实例,并实现更复杂的交互逻辑。

相关推荐
discode7 小时前
【开源项目技术分享】@host-navs 站导,一个简洁高效的网站链接导航工具站
前端
PieroPC7 小时前
Nicegui 3.4.0 可以缩小组件之间的间距 label botton input textarea
前端
写代码的皮筏艇7 小时前
数组 forEach
前端·javascript
shoubepatien8 小时前
JavaWeb_Web基础
java·开发语言·前端·数据库·intellij-idea
WordPress学习笔记8 小时前
wordpress外贸主题Google地图添加(替换)方案
前端·wordpress·wordpress地图
码农秋9 小时前
Element Plus DatePicker 日期少一天问题:时区解析陷阱与解决方案
前端·vue.js·elementui·dayjs
未来之窗软件服务9 小时前
未来之窗昭和仙君(五十六)页面_预览模式——东方仙盟筑基期
前端·仙盟创梦ide·东方仙盟·昭和仙君·东方仙盟架构
top_designer9 小时前
Illustrato:钢笔工具“退休”了?Text to Vector 零基础矢量生成流
前端·ui·aigc·交互·ux·设计师·平面设计
星哥说事9 小时前
星哥带你玩飞牛NAS-13:自动追番、订阅下载 + 刮削,动漫党彻底解放双手!
前端
donecoding9 小时前
前端AI开发:为什么选择SSE,它与分块传输编码有何不同?axios能处理SSE吗?
前端·人工智能