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

Ionic + React应用中IonModal内的IonInput/OtpInput如何实现自动聚焦

Ionic + React 弹窗内输入框自动聚焦解决方案

核心失效原因

IonModal 组件内部DOM挂载存在时序差:当 isOpen 设为true时,子元素不会立刻完成挂载插入文档流,此时内置的autofocus属性、第三方组件的自动聚焦逻辑都会因为目标元素不存在而失效。

可用方案

1. 监听Modal完全展示事件触发聚焦(最稳定)

IonModal 暴露了 onIonModalDidPresent 事件,该事件仅在Modal完全渲染完成、可交互后触发,此时再执行聚焦逻辑可稳定命中目标元素。
代码示例:

import { useRef } from 'react';
import OtpInput from "react-otp-input"; 
import { IonInput, IonModal } from '@ionic/react';

const OtpModal = (props) => {
  // OtpInput 对应ref,绑定内部第一个输入框
  const otpInputRef = useRef<HTMLInputElement>(null);
  // IonInput 对应ref
  const ionInputRef = useRef<HTMLIonInputElement>(null);

  const onModalReady = () => {
    // 聚焦Otp输入框
    otpInputRef.current?.focus();
    // 若需要聚焦IonInput,调用IonInput内置的setFocus方法
    // ionInputRef.current?.setFocus();
  };

  return (
    <IonModal 
      isOpen={true} 
      cssClass={classes.someClass} 
      showBackdrop={false}
      // 关键:绑定Modal就绪事件
      onIonModalDidPresent={onModalReady}
    >
      <OtpInput
        value={props.otp}
        numInputs={6}
        // 绑定ref到第一个输入框
        inputRef={otpInputRef}
      />
      {/* IonInput写法示例
      <IonInput
        ref={ionInputRef}
        type="number"
        label="Enter OTP"
      /> */}
    </IonModal>
  );
};

2. 兼容旧版react-otp-input的方案

如果你使用的react-otp-input版本不支持inputRef属性,可以给输入框加自定义类名,在Modal就绪后通过选择器查找元素:

const onModalReady = () => {
  const firstOtpInput = document.querySelector('.custom-otp-input input:first-of-type') as HTMLInputElement;
  firstOtpInput?.focus();
};

// OtpInput配置
<OtpInput
  value={props.otp}
  numInputs={6}
  containerStyle="custom-otp-input"
/>

注意事项

  • 不要依赖原生autofocus属性,Ionic生态下弹窗内元素的原生自动聚焦兼容性极差
  • IonInput不要直接调用原生DOM的focus方法,必须使用组件暴露的setFocus()异步方法
  • Modal每次打开都会触发onIonModalDidPresent事件,无需额外处理重复打开的聚焦逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 03:15:04