如何使用 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>
  );
}

参考链接

相关推荐
泯泷13 分钟前
「译」解析 JavaScript 中的循环依赖
前端·javascript·架构
抹茶san16 分钟前
前端实战:从 0 开始搭建 pnpm 单一仓库(1)
前端·架构
Senar43 分钟前
Web端选择本地文件的几种方式
前端·javascript·html
烛阴1 小时前
UV Coordinates & Uniforms -- OpenGL UV坐标和Uniform变量
前端·webgl
姑苏洛言1 小时前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
烛阴1 小时前
JavaScript 的 8 大“阴间陷阱”,你绝对踩过!99% 程序员崩溃瞬间
前端·javascript·面试
lh_12542 小时前
ECharts 地图开发入门
前端·javascript·echarts
jjw_zyfx2 小时前
成熟的前端vue vite websocket,Django后端实现方案包含主动断开websocket连接的实现
前端·vue.js·websocket
Mikey_n2 小时前
前台调用接口的方式及速率对比
前端