You need to enable JavaScript to run this app. React JS中如何校验随机生成的移动端OTP完成手机号验证
优惠活动
大模型
产品
解决方案
定价
更多

React JS中如何校验随机生成的移动端OTP完成手机号验证

手机号验证功能实现落地方案

组件流程串联逻辑

采用父组件做流程状态机的模式,避免跨组件状态耦合:

  • 顶层父组件维护两个核心状态:currentStep(可选值mobileInput/otpInput)、boundMobile(存储校验通过的有效手机号)
  • MobileNo组件提交校验通过后,触发父组件回调:将currentStep切换为otpInput,把当前提交的有效手机号写入boundMobile状态
  • MobileOtp组件挂载时,从父组件读取boundMobile作为校验请求的必填参数,不额外在组件内重复存手机号
    该模式直接解决状态赋值不匹配问题:所有跨组件共享状态全部上提,两个子组件仅维护自身的输入值、错误提示、按钮loading状态

补全字段校验逻辑

MobileNo组件规则

  • 输入阶段自动过滤非数字字符,限制最大输入长度10位
  • 提交前强制校验:手机号长度严格等于10位、首位不为0
  • 校验不通过时在输入框下方展示明确错误提示,提交按钮置灰不触发请求
    核心实现代码:
const [mobile, setMobile] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);

const handleMobileInput = (e) => {
  // 过滤非数字,截取前10位
  const inputValue = e.target.value.replace(/\D/g, '').slice(0, 10);
  setMobile(inputValue);
  // 输入时自动清除错误提示
  if (error) setError('');
};

const handleSubmitMobile = async () => {
  if (mobile.length !== 10) {
    setError('请输入10位有效手机号');
    return;
  }
  if (mobile[0] === '0') {
    setError('手机号不能以0开头');
    return;
  }
  setLoading(true);
  try {
    // 本地测试可使用Math.floor(1000 + Math.random() * 9000)生成OTP
    const testOtp = Math.floor(1000 + Math.random() * 9000);
    // 调用后端接口将OTP与手机号绑定存储
    await saveOtpToBackend(mobile, testOtp);
    // 触发父组件切换到OTP输入步骤
    onMobileVerified(mobile);
  } catch (err) {
    setError('提交失败,请稍后重试');
  } finally {
    setLoading(false);
  }
};

MobileOtp组件规则

  • 输入阶段自动过滤非数字字符,限制最大输入长度4位
  • 提交前强制校验:OTP长度严格等于4位
  • 内置60秒重发倒计时,倒计时未结束时禁用重发按钮
    核心实现代码:
const [otp, setOtp] = useState('');
const [error, setError] = useState('');
const [countdown, setCountdown] = useState(60);
const [loading, setLoading] = useState(false);

// 倒计时逻辑
useEffect(() => {
  if (countdown <= 0) return;
  const timer = setTimeout(() => setCountdown(prev => prev - 1), 1000);
  return () => clearTimeout(timer);
}, [countdown]);

const handleOtpInput = (e) => {
  const inputValue = e.target.value.replace(/\D/g, '').slice(0,4);
  setOtp(inputValue);
  if (error) setError('');
};

const handleSubmitOtp = async () => {
  if (otp.length !== 4) {
    setError('请输入4位有效OTP');
    return;
  }
  setLoading(true);
  try {
    // 调用后端接口比对OTP
    const isValid = await validateOtpFromBackend(boundMobile, otp);
    if (!isValid) {
      setError('OTP错误,请重新输入');
      return;
    }
    // 校验通过,触发后续业务逻辑
    onOtpVerified();
  } catch (err) {
    setError('校验失败,请稍后重试');
  } finally {
    setLoading(false);
  }
};

OTP比对校验逻辑

  • 后端存储规则:OTP生成后与对应手机号绑定,设置5分钟有效期,同一手机号重复提交OTP请求时,直接覆盖旧的OTP记录
  • 校验流程:
    1. MobileOtp组件提交时,将用户输入的OTP与绑定的手机号一起传给后端校验接口
    2. 后端首先查询存储中对应手机号的OTP记录:若记录不存在、已过有效期,直接返回校验失败
    3. 若记录有效,比对用户传入的OTP与存储的OTP值:完全一致则返回校验通过,同时删除该OTP记录防止重复使用;不一致直接返回失败

生产环境禁止在前端生成、返回OTP明文,所有OTP的生成、存储、比对逻辑全部放在后端实现,避免校验失效。

现有问题修复点

  • 状态不匹配:移除两个子组件之间的状态依赖,所有共享状态全部上提至父组件,保证状态变更时同步更新
  • 校验缺失:输入阶段实时过滤非法字符,提交前做格式、长度校验,输入时自动清除历史错误提示
  • 体验优化:提交时增加loading状态,接口失败时给出明确重试提示,避免用户重复点击提交

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 14:15:02