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

参考链接

相关推荐
小远yyds15 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai1 小时前
uniapp
前端·javascript·vue.js·uni-app
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓3 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4113 小时前
无网络安装ionic和运行
前端·npm
理想不理想v3 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云3 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js