reactjs 处理多个文件时,处于React状态的阵列被覆盖

pvcm50d1  于 2022-12-29  发布在  React
关注(0)|答案(1)|浏览(115)

我有一个系统,一旦用户选择一个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>
x4shl7ld

x4shl7ld1#

为了防止这种情况,我需要停止使用当前状态值来改变状态,这就是导致值被覆盖的原因,结果我应该将MultipleFileTableData.ExcelData.map移到SetMultipleFileTableData中,而使用prevState变量。

SetMultipleFileTableData(prevState => ({...prevState, ExcelData: 
    (
        prevState.ExcelData.map(p => p["Certificate Filename"] === resp.data.UploadedOriginalFileName ? 
            {...p, FileUploaded: 'Y', UploadedFileName: resp.data.UploadedFileName}
            : p
        )
    )
}));

相关问题