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

ReactJS使用Yup做表单校验时数组长度始终为0问题求解

问题原因
  • formSchema.validate 是异步方法,你的代码在同步位置读取数组长度时,校验的回调逻辑还未执行,数组还没有被推入元素,所以长度为0。控制台展示数组有元素是因为控制台对引用类型的打印是懒加载的,你点击展开数组时异步逻辑已经执行完成,和打印当时的数组状态不是同一个时间点的结果。
  • 你用普通变量 let name = [] 存储错误信息,不属于React的响应式状态,就算后续异步逻辑修改了这个数组,React也不会触发组件重新渲染,页面上的长度永远是初始渲染时的0。
  • 校验逻辑直接写在组件根作用域,每次组件重新渲染都会触发一次校验,会产生不必要的性能消耗。
解决方法

将错误列表改为响应式状态,把校验逻辑放到副作用钩子中执行,修改后的代码如下:

import { useState, useEffect } from 'react'
import * as yup from 'yup'

const formSchema = yup.object().shape({
  firstName: yup.string().required(),
  lastName: yup.string().required(),
  email: yup.string().email().required(),
  password: yup.string().min(8).required()
})
export const App = () => {
  const [values, setValues] = useState({
    firstName: '',
    lastName: '',
    email: '',
    password: ''
  })
  // 用state存储错误列表,支持响应式更新
  const [errors, setErrors] = useState([])

  useEffect(() => {
    // 每次values变更时重新执行校验
    formSchema.validate(values, { abortEarly: false })
      .then(() => {
        // 校验通过清空错误
        setErrors([])
      })
      .catch((err) => {
        const errorList = err.inner.map(error => ({ [error.path]: error.message }))
        setErrors(errorList)
      })
  }, [values]) // 依赖values,只有values变化才重新校验

  console.log(errors)
  console.log(errors.length)
  return (
    <div>
      <h1>hello</h1>
      <h1>{errors.length}</h1>
    </div>
  )
}

修改点说明:

  • 用useState定义errors状态存储校验错误,修改后会自动触发组件重新渲染
  • 把校验逻辑包裹在useEffect中,只有表单值values变化时才重新执行校验,避免无效重复执行
  • 校验完成后直接通过setErrors更新状态,确保可以同步拿到最新的错误列表长度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:24:04