如何使用 React 中的 forwardRef

React 中父组件通过 ref 属性可以操作子组件中暴露的实际 DOM 元素或者暴露的自定义函数。实现父组件操作子组件这一功能,需要子组件经过 forwardRef 这个 API 包裹才能支持。

本文介绍如何使用 forwardRef 这一 API 实现父组件获取和操作子组件。

获取和操作子组件中的实际 DOM 元素

子组件中用 forwardRef 包裹函数组件。并且将第二个参数 ref 传给实际 DOM 元素。

MyInput.js

jsx 复制代码
import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  const { label, ...otherProps } = props;
  return (
    <label>
      {label}
      <input {...otherProps} ref={ref} />
    </label>
  );
});

在父组件中,通过 ref 属性绑定子组件, 后续便可以通过绑定的 ref 变量来操作子组件中实际的 DOM 元素。如获取元素长度宽度,使元素聚焦的方法。

App.js

jsx 复制代码
function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
  }

  return (
    <form>
      <MyInput label="Enter your name:" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}

获取子组件中的暴露的函数

在一些场景下,可能需要从父组件中获取到自组件中定义的一些函数。实现这一功能也是通过 forwardRef 包裹函数组件,然后通过 useImperativeHandle 这个 hook 来暴露可被父组件调用的函数。

MyInput.js

jsx 复制代码
import { forwardRef, useRef, useImperativeHandle } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => {
    return {
      focus() {
        inputRef.current.focus();
      },
      scrollIntoView() {
        inputRef.current.scrollIntoView();
      },
    };
  }, []);

  return <input {...props} ref={inputRef} />;
});

在父组件中,通过 ref 属性来操作子组件暴露的函数。

App.js

jsx 复制代码
import { useRef } from 'react';
import MyInput from './MyInput.js';

export default function Form() {
  const ref = useRef(null);

  function handleClick() {
    ref.current.focus();
    // This won't work because the DOM node isn't exposed:
    // ref.current.style.opacity = 0.5;
  }

  return (
    <form>
      <MyInput placeholder="Enter your name" ref={ref} />
      <button type="button" onClick={handleClick}>
        Edit
      </button>
    </form>
  );
}

参考链接

相关推荐
用户2181697049301 小时前
Flutter(四)Dart语法 空安全 运算符 流程控制
前端
许彰午1 小时前
政务督办的分合模式:主办协办的并发审批
前端·javascript·政务
用户69371750013841 小时前
AI时代,程序员该往哪走?
前端·后端
ttwuai1 小时前
GoFrame 后台日志清空失败:无 WHERE 删除为什么被拦住
前端·golang
易筋紫容1 小时前
创建型模式:对象的诞生艺术
开发语言·前端·javascript
半句唐诗2 小时前
我是如何通过 Access Token 成功发布第一个 npm 包的
前端·npm·node.js
程序员黑豆2 小时前
鸿蒙应用开发:@Provider 与 @Consumer 跨组件双向同步详解
前端·harmonyos
paopaokaka_luck2 小时前
基于springboot3+vue3的智能文库平台(AI智能搜索、AI智能汇总、实时在线状态展示、多格式文档预览与富文本编辑、Echarts图形化分析)
前端·网络·spring boot·网络协议·echarts
牧艺2 小时前
cos-design PhotoAlbum:用 CSS 3D 做一个「能翻页」的实体相册
前端·css·交互设计
洪贺2 小时前
从原始采样到可缩放心电图:用 h5ECG 绘制自己的 ECG
前端