You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

需向父组件透传ref时,React子组件如何判断输入框是否获焦?

解决React子组件判断输入框焦点状态的问题

你可以通过两种方式实现需求,既兼容父组件传入的可选inputRef,又能在子组件内跟踪输入框的焦点状态:

方案一:用状态直接跟踪焦点(推荐,无需额外ref)

通过onFocus和onBlur事件更新子组件内部状态,同时保留父组件传入的事件回调:

import React, { useState, FocusEventHandler } from "react";
import { RefCallBack } from "react-hook-form";

interface IInput {
  inputRef?: RefCallBack;
  onFocus?: FocusEventHandler<HTMLInputElement>;
  onBlur?: FocusEventHandler<HTMLInputElement>;
}
const Input: React.FC<IInput> = ({ inputRef, onFocus, onBlur }) => {
  // 内部状态跟踪焦点状态
  const [isFocused, setIsFocused] = useState(false);

  const handleFocus: FocusEventHandler<HTMLInputElement> = (e) => {
    setIsFocused(true);
    // 调用父组件传入的onFocus回调(如果存在)
    onFocus?.(e);
  };

  const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
    setIsFocused(false);
    // 调用父组件传入的onBlur回调(如果存在)
    onBlur?.(e);
  };

  return (
    <div className={isFocused ? "input-container-focused" : ""}>
      <input 
        type="text" 
        ref={inputRef} 
        onFocus={handleFocus} 
        onBlur={handleBlur} 
      />
    </div>
  );
};

export default Input;

你可以直接用isFocused状态控制样式,比如给外层容器添加聚焦专属类名。

方案二:合并内部ref与父组件传入的ref

如果需要直接通过DOM元素判断焦点(比如检查document.activeElement),可以创建内部ref,并将其与父组件的inputRef合并:

import React, { useRef, useState, FocusEventHandler } from "react";
import { RefCallBack } from "react-hook-form";

interface IInput {
  inputRef?: RefCallBack;
  onFocus?: FocusEventHandler<HTMLInputElement>;
  onBlur?: FocusEventHandler<HTMLInputElement>;
}
const Input: React.FC<IInput> = ({ inputRef, onFocus, onBlur }) => {
  const internalRef = useRef<HTMLInputElement>(null);
  const [isFocused, setIsFocused] = useState(false);

  // 合并ref回调:同时传递元素给内部ref和父组件的inputRef
  const mergedRef = (element: HTMLInputElement | null) => {
    internalRef.current = element;
    inputRef?.(element);
  };

  const handleFocus: FocusEventHandler<HTMLInputElement> = (e) => {
    setIsFocused(true);
    onFocus?.(e);
  };

  const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
    setIsFocused(false);
    onBlur?.(e);
  };

  // 额外监听全局焦点变化,处理输入框被外部元素夺走焦点的场景
  React.useEffect(() => {
    const checkFocus = () => {
      setIsFocused(document.activeElement === internalRef.current);
    };
    window.addEventListener("focus", checkFocus, true);
    window.addEventListener("blur", checkFocus, true);
    return () => {
      window.removeEventListener("focus", checkFocus, true);
      window.removeEventListener("blur", checkFocus, true);
    };
  }, []);

  return (
    <div className={isFocused ? "input-container-focused" : ""}>
      <input 
        type="text" 
        ref={mergedRef} 
        onFocus={handleFocus} 
        onBlur={handleBlur} 
      />
    </div>
  );
};

export default Input;

这个方案通过合并ref,既不影响父组件对输入框的引用,又能在子组件内拿到DOM元素,结合全局焦点事件确保状态准确。

内容的提问来源于stack exchange,提问作者M S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:43:20