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

React状态未即时更新求助:react-otp-input遇状态滞后问题

React OTP输入框状态更新与倒计时问题解决

核心问题分析

  1. OTP长度判断滞后:删除字符时,依赖state中的otp值判断长度会因为React状态更新的异步性,拿到的是更新前的旧值,导致长度计算始终慢一步。
  2. 倒计时逻辑无法在useEffect中执行:直接在useEffect中设置定时器可能因依赖项配置不当,导致定时器无法触发。

解决方案

1. 基于最新输入值判断长度

在OTPInput的onChange回调中,直接使用回调参数value(当前最新的OTP输入值)进行长度判断,而非依赖state中的otp,避免异步更新导致的滞后问题。

2. 直接在输入回调中处理禁用与倒计时

放弃在useEffect中处理定时器,改为在onChange里触发倒计时逻辑,同时添加定时器清理逻辑,防止重复触发导致的异常。

修改后的代码示例

import React, { useState, useRef } from "react";
import OTPInput from "react-otp-input";
import "./styles.css";

export default function App() {
  const [otp, setOtp] = useState("");
  const [isDisabled, setIsDisabled] = useState(false);
  const timerRef = useRef(null); // 用于存储定时器ID,方便清理

  const handleOtpChange = (value) => {
    setOtp(value);

    // 清理之前的定时器,避免重复触发
    if (timerRef.current) {
      clearTimeout(timerRef.current);
    }

    // 当输入长度达到4时,禁用输入框并启动倒计时
    if (value.length === 4) {
      setIsDisabled(true);
      timerRef.current = setTimeout(() => {
        setIsDisabled(false);
      }, 5000);
    }
  };

  // 组件卸载时清理定时器,防止内存泄漏
  React.useEffect(() => {
    return () => {
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
    };
  }, []);

  return (
    <div className="App">
      <h1>OTP Input Test</h1>
      <OTPInput
        value={otp}
        onChange={handleOtpChange}
        numInputs={4}
        isDisabled={isDisabled}
        renderSeparator={<span>-</span>}
        renderInput={(props) => <input {...props} />}
      />
    </div>
  );
}

关键优化点说明

  • 使用onChange回调的value参数获取实时输入值,确保长度判断准确。
  • 通过useRef存储定时器ID,在每次触发输入时清理旧定时器,避免多个定时器同时运行。
  • 组件卸载时清理定时器,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:50:30