useRef、useImperativeHandle 和 forwardRef

useRefuseImperativeHandle 和 forwardRef 是 React 中用于处理 引用(Ref) 的三个重要 API。它们通常用于直接访问 DOM 元素或子组件的实例。以下是它们的详细说明和用法:


1. useRef

useRef 是一个 Hook,用于创建一个可变的引用对象。它的主要用途包括:

  • 访问 DOM 元素。

  • 存储可变值(类似于类组件的实例变量)。

1.1 基本用法
import React, { useRef } from 'react';

function MyComponent() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}
1.2 特点
  • useRef 返回的对象在组件的整个生命周期内保持不变。

  • 修改 ref.current 不会触发组件的重新渲染。

2. forwardRef

forwardRef 用于将 ref 从父组件传递到子组件。通常用于封装第三方组件或高阶组件。

2.1 基本用法
import React, { useRef, forwardRef } from 'react';

// 子组件
const ChildComponent = forwardRef((props, ref) => {
  return <input type="text" ref={ref} />;
});

// 父组件
function ParentComponent() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <ChildComponent ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}
2.2 特点
  • forwardRef 允许父组件直接访问子组件的 DOM 元素或实例。

  • 适用于封装需要暴露 ref 的自定义组件。

3.1 基本用法
import React, { useRef, forwardRef, useImperativeHandle } from 'react';

// 子组件
const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  // 自定义暴露给父组件的 ref 值
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    getValue: () => {
      return inputRef.current.value;
    },
  }));

  return <input type="text" ref={inputRef} />;
});

// 父组件
function ParentComponent() {
  const childRef = useRef(null);

  const handleClick = () => {
    childRef.current.focus(); // 调用子组件暴露的方法
    console.log('Input Value:', childRef.current.getValue()); // 获取输入框的值
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Focus Input and Get Value</button>
    </div>
  );
}

4. 三者的结合使用

useRefforwardRef 和 useImperativeHandle 通常结合使用,以实现更灵活的 ref 管理。

示例:封装一个可控制的输入框组件
import React, { useRef, forwardRef, useImperativeHandle } from 'react';

// 子组件
const ControlledInput = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    clear: () => {
      inputRef.current.value = '';
    },
  }));

  return <input type="text" ref={inputRef} />;
});

// 父组件
function ParentComponent() {
  const inputRef = useRef(null);

  const handleFocus = () => {
    inputRef.current.focus();
  };

  const handleClear = () => {
    inputRef.current.clear();
  };

  return (
    <div>
      <ControlledInput ref={inputRef} />
      <button onClick={handleFocus}>Focus Input</button>
      <button onClick={handleClear}>Clear Input</button>
    </div>
  );
}
API用途
useRef创建可变引用,用于访问 DOM 元素或存储可变值。
forwardRef将 ref 从父组件传递到子组件,适用于封装需要暴露 ref 的组件。
useImperativeHandle自定义暴露给父组件的 ref 值,限制父组件对子组件的访问权限。

通过合理使用这三个 API,可以实现更灵活的 ref 管理,提升组件的可复用性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值