如何在 React 中正确使用 useRef 来访问子组件的 DOM 节点?

如何在 React 中正确使用 useRef 来访问子组件的 DOM 节点?

回答与解析:

在 React 中,useRef 本身不能直接用于访问函数组件(子组件)的 DOM 节点,因为函数组件没有实例。若要从父组件访问子组件内部的 DOM 元素,需使用 forwardRef 和 useImperativeHandle。

正确做法如下:

  1. 子组件使用 React.forwardRef 包裹,并通过 ref 接收父组件传递的引用;
  2. 在子组件内部,使用 useRef 创建对实际 DOM 节点的引用;
  3. 使用 useImperativeHandle 暴露需要让父组件访问的方法或 DOM 节点。

示例代码:

// 子组件
import { forwardRef, useRef, useImperativeHandle } from 'react';

const Child = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focus: () => inputRef.current.focus(),
    getInputElement: () => inputRef.current
  }));

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

// 父组件
const Parent = () => {
  const childRef = useRef();

  const handleClick = () => {
    childRef.current.focus(); // 调用子组件暴露的方法
  };

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
};

关键点解析:

  • 直接给函数组件添加 ref 会报错或无效;
  • forwardRef 使得 ref 可以被传递到函数组件内部;
  • useImperativeHandle 控制暴露给父组件的 API,避免直接暴露整个 DOM 节点(更安全可控);
  • 此模式常用于表单控件、动画组件、自定义焦点管理等场景。

注意:应尽量避免过度使用 ref 操作 DOM,优先考虑通过状态和 props 实现声明式 UI。

发表评论 (审核通过后显示评论):

昵称:
邮箱:
内容: