react hook + antd upload 通过fileList控制文件列表展示status为uploading

项目是用的react hook写的,引入了antd 的upload上传组件,页面效果如下

代码

import React, { useState } from 'react'
import { Modal, Form, Upload, message, Button } from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import { TableListItem } from '@/services/data.d'
import { importByExcelUrl } from '@/services/manually'
import { validFileSize } from '@/utils/validate'

export interface FormValueType extends Partial<TableListItem> {
  time?: string;
  [propName: string]: any
}

const FormItem = Form.Item

interface CreateFormProps {
  modalVisible: boolean;
  onCancel: () => void;
  onConfirm: (values: FormValueType) => void;
  values: any
}
const formLayout = {
  labelCol: { span: 7 },
  wrapperCol: { span: 13 },
}

const UploadForm: React.FC<CreateFormProps> = (props) => {
  const { modalVisible, onConfirm, onCancel } = props
  const [bussinessFileList, setFilelist] = useState<any[]>([])
  const [uploadFileList, setUploadFilelist] = useState<any[]>([])
  const [form] = Form.useForm()

  form.setFieldsValue({})

  const uploadprops = {
    name: 'file',
    action: importByExcelUrl(),
    headers: {
      authorization: 'authorization-text',
    },
    accept:
      '.csv,.xls,.xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel',
    data: { businessCode: props.values },
    disabled: bussinessFileList.length === 1,
    fileList: uploadFileList,
    beforeUpload(file: any) {
      // console.log(6, file, uploadFileList.length, validFileSize(file))
      if (uploadFileList.length > 0) {
        message.warning('只能上传一个文件')
        return false
      }
      if (file.size === 0) {
        message.error('文件不能为空')
        return false
      }
      return validFileSize(file)
    },
    onChange(info: any) {
      let files: any[] = [...info.fileList]
      if (info.file.status === 'done') {
        if (info.file.response) {
          if (info.file.response.responseCode === '000000') {
            // files = [...info.fileList]
            message.success(`${info.file.name} 文件上传成功`)
          } else {
            message.error(info.file.response.responseMsg)
          }
        } else {
          message.error(`${info.file.name} 上传失败.`)
        }
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} 上传失败.`)
      }
      files = files.filter((item : any) => {
        return item.response?.responseCode === '000000'
      })
      files = JSON.parse(JSON.stringify(files))
      console.log(66666, info, files)
      setUploadFilelist(files)
      setFilelist(files)
    },
  }

  const renderContent = () => {
    return (
      <>
        <FormItem
          name='uploads'
          label='上传模板'
          required
          rules={[{ validator: (rule, value, callback) => {
            if (value && value.fileList && value.fileList.length) {
              console.log(77, value)
              if (value.file.response && value.file.response.responseCode === '000000') {
                callback()
              } else if (value.file.status && value.file.status === 'uploading') {
                callback()
              } else {
                callback('文件信息有误,请删除后上传正确文件')
              }
            } else callback('请选择文件上传')
          } }]}
        >
          <Upload {...uploadprops}>
            <Button>
              <UploadOutlined /> 点击上传
            </Button>
          </Upload>
        </FormItem>
      </>
    )
  }
  const handleConfirm = async() => {
    const fieldsValue = await form.validateFields()
    // console.log(fieldsValue)
    onConfirm(fieldsValue)
  }

  return (
    <Modal
      destroyOnClose
      title='上传模板'
      visible={modalVisible}
      onOk={() => handleConfirm()}
      maskClosable={false}
      onCancel={() => onCancel()}
    >
      <Form
        {...formLayout}
        form={form}
        initialValues={{}}
      >
        {renderContent()}
      </Form>
    </Modal>
  )
}

export default UploadForm

想做到的效果是用户文件上传正确,才展示在页面上,上传错误不展示在页面上.使用了upload的fileList属性,发现文件上传状态一直是uploading

在官网找了一圈答案https://github.com/ant-design/ant-design/issues/2423这个issue里有问题描述,试了里面的一些方法还是不起作用

后面发现实际问题是,fileList这个属性不能设置为空数组

这里已经说得很明白了,所以说想用这个属性来控制文件,就必须保证不会为空数组,但是这个跟我的需求不符,所以后来没用这个属性,是用form的rules来提示客户删除不正确的文件重新上传

但是如果一定要实现这个功能可以自己写fileList

 <FormItem
          name='uploads'
          label='上传模板'
          required
          rules={[{ validator: (rule, value, callback) => {
            if (value && value.fileList && value.fileList.length) {
              console.log(77, value)
              if (value.file.response && value.file.response.responseCode === '000000') {
                callback()
              } else if (value.file.status && value.file.status === 'uploading') {
                callback()
              } else {
                callback('文件信息有误,请删除后上传正确文件')
              }
            } else callback('请选择文件上传')
          } }]}
        >
          <>
            <Upload {...uploadprops} showUploadList={false}>
              <Button>
                <UploadOutlined /> 点击上传
              </Button>
            </Upload>
            {bussinessFileList.length ? <ul>     // 大概的就是这样,具体样式自己要调整一下
              {bussinessFileList.map(item => <li key={item.uid}>
                {item.name}
              </li>)}
            </ul> : null}
          </>
        </FormItem>

这样写要注意一个问题,formtien默认值会获取内部的一个闭合标签的值,这里加了列表之后,form rules里面的value将会获取不到file上传的内容,可以换成bussinessFileList判断

 
原文地址:https://www.cnblogs.com/steamed-twisted-roll/p/13255417.html