我有一个系统,一旦用户选择一个Excel文件,该文件被读入状态MultipleFileTableData.ExcelData
,然后使用AntD表显示。
当用户选择文件时,该文件被上载到API,API返回原始文件名和存储在系统中的文件名。
一旦文件被上载,数据随后被更新以指示文件已经上载,并且存储在系统中的文件名被添加。
如果只选择了一个文件,上面的方法就可以很好地工作,但是系统需要允许多个文件。一旦你选择了多个文件上传,状态就会被覆盖。简而言之,第一个文件行会更新为上传文件的标志和存储的文件名。但是一旦处理了第二个文件,第一个文件就会恢复。
我已经省略了大部分的代码,因为我相信它是不相关的。代码如下:
const CertificateUploadMultiple = ({FormState, SetFormState}) => {
const { Dragger } = Upload;
const [MultipleFileTableData, SetMultipleFileTableData] = useState({ExcelData: []});// userRef([]); // This holds the data from the imported excel file
const BatchUploadTableColumns = [
{title: 'Customer', dataIndex: 'Customer Name', key: 'Customer Name'},
{title: 'Serial Number', dataIndex: 'Serial Number', key: 'Serial Number'},
{title: 'Certificate Number', dataIndex: 'Certificate Number', key: 'Certificate Number'},
{title: 'Certificate Date', dataIndex: 'Certificate Date', key: 'Certificate Date'},
{title: 'Certificate File', dataIndex: 'Certificate Filename', key: 'Certificate Filename'},
{title: 'Certificate Uploaded', align: 'right', render: (text, record, index) => {
return (<>
{record['FileUploaded'] == 'Y' ? <span>File uploaded</span> : <span>Awaiting File</span>}
<Button danger size='small' style={{marginLeft: "0.5em"}} onClick={() => {DeleteExcelRowData(text, record, index);}}><DeleteOutlined /></Button>
</>)
}
},
]
const ReadTemplateFile = async (e) => {
console.log("ReadTemplateFile", e);
const AllowedFiles = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
if (!AllowedFiles.includes(e.type)) {
let Content = <><p>'{file.name}' is not a permitted file</p><p>Received File type: '{file.type}'</p></>;
Modal.error({
title: 'Invalid File',
content: Content
})
return false;
}
const reader = new FileReader();
reader.onload = (evt) => {
const bstr = evt.target.result;
const wb = XLSX.read(bstr, { type: "binary" });
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const RawData = XLSX.utils.sheet_to_json(ws);
console.log("Excel Raw Data", RawData);
const Rows = RawData.map((row, idx) => ({...row, key:idx, FileUploaded: 'N', UploadedFileName: ''}));
SetMultipleFileState(prevState => ({...prevState, ShowTemplateUpload: false}));
SetMultipleFileTableData(prevState => ({...prevState, ExcelData: Rows}));
};
reader.readAsBinaryString(e);
return false;
}
const RowColour = (record) => {
//if (UploadedFileList.includes(record['Certificate Filename'])){
//if (UploadedFileListRef.current.includes(record['Certificate Filename'])){
/*if (record.FileUploaded == 'Y'){
return 'fileuploaded';
}*/
return record.FileUploaded === 'Y' ? 'fileuploaded' : 'awaitingfile';
//return 'awaitingfile';
}
const MultipleCertificateFileUploadProcessFile = async (options) => {
const { onSuccess, onError, file, onProgress } = options;
const UploadProgressHandler = (event) => {
const percent = Math.floor((event.loaded / event.total) * 100);
setProgress(percent);
if (percent === 100) {
setTimeout(() => setProgress(0), 1000);
}
onProgress({ percent: (event.loaded / event.total) * 100 });
}
const Data = new FormData();
Data.append("CertificateFile", file);
try {
CertificateService.UploadCertificateFile(Data, UploadProgressHandler)
.then((resp) => {
if (resp.data.code == '200'){
// mark the line as completed
/*let idx = MultipleFileTableData.ExcelData.findIndex((obj => obj["Certificate Filename"] === resp.data.UploadedOriginalFileName));
console.log("idx", idx);
let t = MultipleFileTableData.ExcelData[idx];
t.FileUploaded = 'Y';
t.UploadedFileName = resp.data.UploadedFileName;*/
//SetMultipleFileTableData(prevState => ({...prevState, ExcelData: [...prevState.ExcelData, t]}));
let t = MultipleFileTableData.ExcelData.map(p => p["Certificate Filename"] === resp.data.UploadedOriginalFileName ?
{...p, FileUploaded: 'Y', UploadedFileName: resp.data.UploadedFileName}
: p
);
SetMultipleFileTableData(prevState => ({...prevState, ExcelData: t}));
onSuccess("Ok");
} else {
message.error(<div>Unable to process file '{resp.data.CertificateFileName}': {resp.data.msg}</div>)
console.log("Error - ", resp.data);
onError(resp.data);
}
console.log("resp", resp);
});
} catch (err) {
console.log( err);
onError(err);
}
}
这是视觉部分
<Row>
<Col span={20}>
<Table
// dataSource={MultipleFileState.ExcelFileData}
dataSource={MultipleFileTableData.ExcelData}
columns={BatchUploadTableColumns}
rowClassName={RowColour}
pagination={false}
/>
</Col>
<Col span={4}>
<Dragger
name='BatchCertificateFile'
multiple={true}
beforeUpload={MultipleCertificateFileBeforeUpload}
style={{marginLeft: "1em"}}
onChange={MultipleCertificateFileUploadOnChange}
customRequest={MultipleCertificateFileUploadProcessFile}
showUploadList={true}
fileList={MultipleFileState.MultipleCertificateFileList}
>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">Click or drag certificate files to this area to start processing</p>
</Dragger>
</Col>
</Row>
1条答案
按热度按时间x4shl7ld1#
为了防止这种情况,我需要停止使用当前状态值来改变状态,这就是导致值被覆盖的原因,结果我应该将
MultipleFileTableData.ExcelData.map
移到SetMultipleFileTableData
中,而使用prevState
变量。