React中如何设置文件上传在表单提交时才触发
问题根因
你当前代码在文件选择框的onChange回调中直接调用了addFiles方法解析Excel,所以只要选择完文件就会立刻读取数据输出到控制台,和你想要点击Upload按钮再触发的逻辑不符。
调整步骤
- 文件选择框的
onChange事件仅做文件存储,不触发解析逻辑 - 将Excel解析逻辑移到表单提交函数
handleSubmit中,仅当单选框选中Add选项时才执行 - 新增文件存在校验,避免无文件提交时报错
修改后完整代码
import React, { useState } from "react"; import * as XLSX from "xlsx"; import "./../accordian.css"; import { makeStyles } from '@material-ui/core/styles'; import Radio from '@material-ui/core/Radio'; import RadioGroup from '@material-ui/core/RadioGroup'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; import Button from '@material-ui/core/Button'; function Upload() { const useStyles = makeStyles((theme) => ({ formControl: { margin: theme.spacing(3), }, button: { margin: theme.spacing(1, 1, 0, 0), }, })); const [items, setItems] = useState([]); // 存储选中的文件 const [files, setFiles] = useState([]) const classes = useStyles(); const [value, setValue] = React.useState(''); const [error, setError] = React.useState(false); const [helperText, setHelperText] = React.useState('Choose wisely') const handleRadioChange = (event) => { setValue(event.target.value); setHelperText(' '); setError(false); }; const addFiles = (files) => { files.map((file) => { var filereader = new FileReader(); filereader.readAsArrayBuffer(file); filereader.onload = (e) => { const bufferArray = e.target.result; const wb = XLSX.read(bufferArray, { type: "buffer" }); const wsname = wb.SheetNames[0]; const ws = wb.Sheets[wsname]; // 注意:原代码sheet_to_json第二个参数是配置项,不能直接传第二个sheet,需要单独解析第二个sheet再合并数据 const data = XLSX.utils.sheet_to_json(ws); setItems(data); setHelperText('文件已上传解析完成'); }; }); }; const handleSubmit = (event) => { event.preventDefault(); // 先校验是否选了文件 if (files.length === 0) { setHelperText('请先选择要上传的Excel文件'); setError(true); return; } if (value === 'Add') { setHelperText('正在解析文件...'); setError(false); // 选中Add时才执行文件解析逻辑 addFiles(files); } else if (value === 'Replace') { setHelperText('File Replaced'); setError(true); } else if (value === 'Remove') { setHelperText('File Removed'); setError(true); } else { setHelperText('Please select an option.'); setError(true); } } console.log(items, 'item'); return ( <div className="container-fluid"> <form onSubmit={handleSubmit}> <FormControl component="fieldset" error={error} className={classes.formControl}> <section className="heading"> <input type="file" className="input-field" accept=".csv, .xlsx,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" onChange={(e) => { // 仅存储选中的文件,不做解析 setFiles([...e.target.files]); }} multiple /> </section> <RadioGroup aria-label="quiz" name="quiz" value={value} onChange={handleRadioChange}> <FormControlLabel value="Add" control={<Radio />} label="Add" /> <FormControlLabel value="Replace" control={<Radio />} label="Replace" /> <FormControlLabel value="Remove" control={<Radio />} label="Remove" /> </RadioGroup> <FormHelperText>{helperText}</FormHelperText> <Button type="submit" variant="outlined" color="primary" className={classes.button} > Upload </Button> </FormControl> </form> </div> ); } export default Upload;
补充说明
原代码中XLSX.utils.sheet_to_json(ws, ws1)写法有误,第二个参数为解析配置项,如果需要读取两个sheet的数据,需要分别解析后再合并。
内容的提问来源于stack exchange,提问作者Rashmi UI
相关产品推荐
相关产品推荐

