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

参考链接

相关推荐
程序员辉哥1 分钟前
学会在Cursor中使用Rules生成代码后可以躺平了吗?
前端·后端
请你吃div6 分钟前
JavaScript 实用函数大全(超实用)
前端·javascript·面试
一个水瓶座程序猿.7 分钟前
Vue3 中使用 Vueuse
前端·javascript·vue.js
夏梦春蝉8 分钟前
ES6从入门到精通:Symbol与迭代器
前端·javascript·es6
一个水瓶座程序猿.11 分钟前
ES6数组的`flat()`和`flatMap()`函数用法
前端·ecmascript·es6
袁煦丞27 分钟前
AI直接出答案!Perplexica开源搜索引擎:cpolar内网穿透实验室第534个成功挑战
前端·程序员·远程工作
Hilaku29 分钟前
用“人话”讲明白10个最常用的正则表达式
前端·javascript·正则表达式
木叶丸38 分钟前
跨平台方案该如何选择?
android·前端·ios
LL.。41 分钟前
同步回调和异步回调
开发语言·前端·javascript
网络点点滴1 小时前
Vue如何处理数据、v-HTML的使用及总结
前端·vue.js·html