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

Formik onChange中errors存在异步更新延迟,如何无延迟获取校验结果

问题原因

Formik的状态(包括errors、touched、values等)采用异步批量更新机制,你在自定义onChange函数中先读取errors时,handleChange还未执行完成,Formik还没有触发校验并更新errors对象,因此你拿到的是上一次渲染的旧校验结果,自然会出现延迟。

解决方案

方案1:手动调用Yup校验(无延迟,推荐)

直接复用已定义的Yup校验规则,对当前输入值做实时校验,不需要依赖Formik的异步状态更新,实现无延迟判断:
首先抽离公共校验规则:

const validationSchema = Yup.object({
  name: Yup.string().required()
})

修改自定义onChange逻辑:

async function onChange(e) {
  const fieldName = e.target.name
  const fieldValue = e.target.value
  try {
    // 直接校验当前输入值,不依赖Formik的errors状态
    await validationSchema.validateAt(fieldName, { [fieldName]: fieldValue })
    // 校验通过后再触发dispatch
    dispatch(setInvitationConfigParam({ name: fieldName, value: fieldValue }))
  } catch (err) {
    // 校验不通过,不执行任何操作
  }
  handleChange(e)
}

方案2:通过useEffect监听Formik状态更新

如果你不想手动调用校验逻辑,可以将dispatch逻辑放到useEffect中,等Formik的状态更新完成后再做判断:

import { useEffect } from 'react'

// 监听name字段的输入和校验结果变化
useEffect(() => {
  // 仅当name字段无校验错误、且已被用户操作过才触发提交
  if (!errors.name && touched.name) {
    dispatch(setInvitationConfigParam({ name: 'name', value: formik.values.name }))
  }
}, [formik.values.name, errors.name, touched.name, dispatch])

此时输入框不需要自定义onChange,直接绑定Formik默认的handleChange即可:

<InputWrapper>
  <TextInput
   customClass="input"
   error={false}
   textFieldProps={{
   label: t('configurationForm.settings.nameConfiguration'),
   error: hasErrors('name', errors, touched),
   helperText: getErrors('name', errors, touched),
   ...getFieldProps('name'),
}}
tooltipTitle={t('configurationForm.settings.nameConfigurationDescription')}
/>
注意事项
  • 如果仅需判断name单个字段的校验结果,不要直接判断Object.keys(errors).length === 0,直接判断!errors.name即可,避免其他字段的校验结果干扰当前逻辑
  • 如果需要实时提交,建议添加防抖逻辑,避免用户输入过程中频繁触发dispatch

内容的提问来源于stack exchange,提问作者Mateusz Matuś Kowalski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:06:04