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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:30:05