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

React中使用Formik实现父组件对子组件文件上传校验

Formik文件上传组件文件名特殊字符校验实现方案

核心逻辑保持你现有「父层validationSchema统一管控所有校验规则」的架构不变,同时实现文件上传(含点击选择、拖拽两种场景)瞬间实时展示错误提示,不需要额外新增独立的错误状态。


步骤1:在全局校验Schema中补充文件名校验规则

首先把文件名合法性规则写入父层的OrderValidationSchema,保证提交时的全局拦截逻辑统一。

注意:把文件名校验的正则抽成公共常量,后续Schema和上传组件共用,避免两处规则不一致。

// 公共常量文件中定义,按需调整你需要拦截的特殊字符范围
export const VALID_FILENAME_REGEX = /^[a-zA-Z0-9_\-\u4e00-\u9fa5.]+$/; // 示例规则:仅允许中英文、数字、下划线、横杠、英文点

// OrderValidationSchema中补充对应字段校验
const OrderValidationSchema = Yup.object().shape({
  // 原有其他字段的校验规则完全保留
  // ...
  [OrderForm.formField.orderFilesFe.name]: Yup.array()
    .of(
      Yup.mixed().test(
        'is-valid-filename',
        'Invalid file name',
        (file) => {
          // 标记为已删除的文件跳过校验
          if (!file || file.delete) return true;
          return VALID_FILENAME_REGEX.test(file.name);
        }
      )
    )
  // 原有该字段的其他校验规则(比如必填)保留即可
});

步骤2:修改上传组件的上传逻辑,上传即触发校验

你的上传组件不管是点击选择文件、还是拖拽上传,最终都会走uploadFiles方法,只需要修改这一个方法即可覆盖所有上传场景:

  1. 上传前先过滤掉文件名不符合规则的文件
  2. 主动标记字段为已触碰(touched),触发现有错误提示逻辑
  3. 仅把合法文件加入上传列表

修改后的uploadFiles方法代码如下:

// 注意从公共常量文件引入刚才定义的VALID_FILENAME_REGEX
import { VALID_FILENAME_REGEX } from '@/constants';

const uploadFiles = async (fileList: File[]) => {
  setIsLoading(true)
  try {
    if (!fileList) {
      setIsLoading(false)
      return
    }

    let existingFiles = files == null ? [] : files
    let newList = [...existingFiles]
    const invalidFileNames: string[] = []
    const validFiles: File[] = []

    // 先拆分合法/非法文件
    Array.from(fileList).forEach((newFile) => {
      if (!VALID_FILENAME_REGEX.test(newFile.name)) {
        invalidFileNames.push(newFile.name)
        return
      }
      validFiles.push(newFile)
    })

    // 存在非法文件时,主动触发字段touched状态,展示错误提示
    if (invalidFileNames.length > 0) {
      helpers.setTouched(true, true)
      // 可选:增加轻提示告知用户哪些文件被拦截,比如用项目里的toast组件
      // toast.error(`文件名包含特殊字符,以下文件无法上传:${invalidFileNames.join('、')}`)
    }

    // 仅将合法文件加入列表
    validFiles.forEach((newFile) => {
      let index = newList.findIndex((t) => t.name == newFile.name)
      if (index > -1) {
        newList[index]['delete'] = false
      } else {
        newList.push(newFile)
      }
    })
    onFilesUploadedFn(newList)

    setIsLoading(false)
  } catch (error) {
    alert(error)
    setIsLoading(false)
  }
}

方案适配说明

  • 你现有组件已经实现了meta.touched && meta.error时展示错误文案、上传框变红边框的逻辑,调用helpers.setTouched(true)后会直接复用这套逻辑,不需要额外写样式或错误状态管理
  • 非法文件会被直接拦截,不会出现在已上传列表中,避免用户误以为上传成功
  • 全局提交时的校验逻辑自动生效,不需要额外处理提交拦截
  • 规则统一维护在公共常量+Yup Schema中,后续调整特殊字符拦截范围只需要改一处

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:18:19