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

React中验证码输入框自动切换焦点的优化方案咨询

React验证码输入框自动焦点切换优化方案

方案一:单个容器Ref + 索引控制焦点

这种方案无需给每个输入框单独设置Ref,只需要给包裹输入框的容器加一个Ref,通过容器的children属性定位并切换焦点,同时结合受控组件统一管理验证码状态。

示例代码:

import { useState, useRef } from "react";

function CodeInput() {
  const CODE_LENGTH = 5;
  const [code, setCode] = useState(new Array(CODE_LENGTH).fill(""));
  const inputContainerRef = useRef(null);

  const handleInputChange = (e, index) => {
    // 仅允许输入字母数字
    const value = e.target.value.replace(/[^0-9a-zA-Z]/g, "");
    if (!value) return;

    const newCode = [...code];
    newCode[index] = value;
    setCode(newCode);

    // 输入完成后自动聚焦下一个输入框
    if (index < CODE_LENGTH - 1) {
      inputContainerRef.current.children[index + 1].focus();
    }
  };

  const handleKeyDown = (e, index) => {
    // 退格时,当前输入框为空则聚焦上一个并清空内容
    if (e.key === "Backspace" && !code[index]) {
      e.preventDefault();
      if (index > 0) {
        inputContainerRef.current.children[index - 1].focus();
        const newCode = [...code];
        newCode[index - 1] = "";
        setCode(newCode);
      }
    }
  };

  return (
    <div ref={inputContainerRef} style={{ display: "flex", gap: "8px" }}>
      {code.map((char, index) => (
        <input
          key={index}
          type="text"
          maxLength={1}
          value={char}
          onChange={(e) => handleInputChange(e, index)}
          onKeyDown={(e) => handleKeyDown(e, index)}
          style={{
            width: "40px",
            height: "40px",
            textAlign: "center",
            fontSize: "18px"
          }}
        />
      ))}
    </div>
  );
}

export default CodeInput;

优势:

  • 仅需一个容器Ref,避免手动创建多个独立Ref的繁琐
  • 验证码状态完全由React State管理,避免DOM操作导致的状态不一致
  • 扩展性强:修改验证码长度只需调整CODE_LENGTH常量,无需改动其他逻辑

方案二:动态数组Ref管理

通过useRef创建一个数组存储每个输入框的Ref,动态关联输入框,相比手动创建多个Ref更简洁,适合需要单独控制某个输入框的场景。

示例代码:

import { useState, useRef } from "react";

function CodeInput() {
  const CODE_LENGTH = 5;
  const [code, setCode] = useState(new Array(CODE_LENGTH).fill(""));
  const inputRefs = useRef([]);

  const handleInputChange = (e, index) => {
    const value = e.target.value.replace(/[^0-9a-zA-Z]/g, "");
    if (!value) return;

    const newCode = [...code];
    newCode[index] = value;
    setCode(newCode);

    if (index < CODE_LENGTH - 1) {
      inputRefs.current[index + 1].focus();
    }
  };

  const handleKeyDown = (e, index) => {
    if (e.key === "Backspace" && !code[index]) {
      e.preventDefault();
      if (index > 0) {
        inputRefs.current[index - 1].focus();
        const newCode = [...code];
        newCode[index - 1] = "";
        setCode(newCode);
      }
    }
  };

  return (
    <div style={{ display: "flex", gap: "8px" }}>
      {code.map((char, index) => (
        <input
          key={index}
          ref={(el) => (inputRefs.current[index] = el)}
          type="text"
          maxLength={1}
          value={char}
          onChange={(e) => handleInputChange(e, index)}
          onKeyDown={(e) => handleKeyDown(e, index)}
          style={{
            width: "40px",
            height: "40px",
            textAlign: "center",
            fontSize: "18px"
          }}
        />
      ))}
    </div>
  );
}

export default CodeInput;

优势:

  • 动态关联输入框Ref,逻辑清晰,可直接访问任意位置的输入框
  • 结合受控组件,状态管理更可靠
  • 代码结构简洁,易于维护

方案对比

两种方案都比直接操作DOM或手动创建多个独立Ref更优雅:

  • 容器Ref方案代码更轻量化,无需给每个输入框绑定Ref
  • 数组Ref方案更灵活,适合需要对单个输入框做额外操作的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:06:25