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

React中useRef聚焦失效问题:输入框自动跳转焦点需求实现

解决方案:React实现输入后自动聚焦下一个输入框

你的代码存在几处关键问题导致自动聚焦失效,以下是修正后的完整方案:

问题分析

  1. Ref使用错误:React的useRef需要通过.current属性存储和访问引用,你直接给itemsRef[0]赋值,并未将输入框引用存入持久化的ref容器中。
  2. 聚焦目标错误:你尝试调用ref[i].focus(),但此处ref未定义,正确操作应是获取下一个输入框的引用itemsRef.current[i+1]。
  3. 受控组件处理不当:空的onChange回调无意义,还可能引发警告,需正确实现受控组件逻辑。

修正后的代码

<html>
  <head>
    <title>React App</title>
    <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
  </head>
 
  <body>
    <div id="mydiv"></div>
    <script type="text/babel"> 
      function Inputs() {
        const [otp, setOtp] = React.useState(['', '', '']); // 初始化对应输入框数量的状态
        const itemsRef = React.useRef([]);       // 存储输入框引用的容器

        const handleKeyPress = (e, i) => {
          const key = e.key;
          // 只处理数字键
          if (!isNaN(parseInt(key))) {
            const newOtp = [...otp];
            newOtp[i] = key;
            setOtp(newOtp);
            // 如果不是最后一个输入框,聚焦下一个
            if (i < itemsRef.current.length - 1) {
              itemsRef.current[i + 1]?.focus();
            }
          }
          // 处理退格键,回到上一个输入框
          else if (key === 'Backspace' && i > 0) {
            const newOtp = [...otp];
            newOtp[i] = '';
            setOtp(newOtp);
            itemsRef.current[i - 1]?.focus();
          }
        };

        // 统一渲染输入框,避免重复代码
        const renderInputs = () => {
          return otp.map((value, index) => (
            <input
              key={index}
              placeholder={`input ${index + 1}`}
              type="number"
              className="otpNumber"
              onChange={(e) => {
                // 受控组件的onChange,更新对应位置的状态
                const newOtp = [...otp];
                newOtp[index] = e.target.value;
                setOtp(newOtp);
              }}
              onKeyPress={(e) => handleKeyPress(e, index)}
              ref={(el) => (itemsRef.current[index] = el)}
              autoFocus={index === 0}
              value={value}
              maxLength={1} // 限制只输入一个字符
            />
          ));
        };

        return (
          <div className="space-x-2">
            {renderInputs()}
            <p>输入数字后会自动聚焦下一个输入框,退格会回到上一个</p>
          </div>
        );
      }

      ReactDOM.render(<Inputs />, document.getElementById("mydiv"));
    </script>
  </body>
</html>

关键修正点

  • 正确使用useRef:将输入框引用存入itemsRef.current数组,确保组件重渲染后引用不丢失。
  • 聚焦逻辑修正:通过itemsRef.current[i+1]?.focus()获取并聚焦下一个输入框,用可选链避免越界报错。
  • 优化受控组件:实现正确的onChange回调,添加maxLength={1}限制每个输入框只输入一个字符,适配OTP输入场景。
  • 增加退格处理:补充退格键逻辑,提升用户操作体验。
  • 代码复用:用map渲染输入框,减少重复代码,便于后续扩展输入框数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:35:51