useForm setter 方法未设置文件(React + Inertia.js)

问题描述 投票:0回答:1

我有一个通过 Inertia.js 连接到 Laravel 后端的 React 应用程序。 Inertia 提供了上传文件的简单方法: https://www.inertiajs.com/file-uploads

我的代码与此非常相似,但有些东西阻止设置文件。

这是当我通过选择器选择文件时调用的方法:

    const { data, setData, post, progress, errors, } = useForm({
        recipient: '',
        recipient_mail: '',
        sum: '',
        file: null,
        filename: '',
        type: '',
    })

    const handleFileChange = (e) => {
        const file = e.target.files[0];
        console.log(file); // It's defined here, after selecting a valid file.
        if (file && file.type === 'application/pdf') {
            setData('file', file);
            setData('filename', file.name);
            console.log("File attached");
        } else {
            setFile(null)
            setData('file', null);
            setData('filename', '');
            console.log("No file attached");
        }
    };

但是,如果我之后发布一些调试信息:

    const debugClick = () => {
        console.log("data.file:", data.file); // It's always "null"
        console.log("data.filename:", data.filename); // This is set correctly
    }

虽然所有其他字段(仅字符串和数字)都已正确设置,但文件仍然始终是

null

不用说,如果我尝试提交表单,所选文件不会一起发送。似乎 setter 方法由于某种原因失败了。 作为参考,以下是 pdf 文件(或其中一个,因为我尝试过多个文件)如何显示在

console.log
:

File { name: "invoice_dummy.pdf", lastModified: 1725345145845, webkitRelativePath: "", size: 102020, type: "application/pdf" }
create.jsx:24:16

作为替代方案,我尝试使用 React 的

useEffect
,创建一个
FormData
对象并通过
formData.append()
附加文件。在这种情况下,useEffect 的 setter 方法按预期设置文件,但
formData.append
没有添加任何内容。

为了完整起见,这里还有输入字段:

                                    <input type="file"
                                        id="document_pdf"
                                        name="file"
                                        accept=".pdf,application/pdf"
                                        value={data.file}
                                        className="mt-1 block w-full"
                                        onChange={handleFileChange}
                                    />

我觉得要么我忽略了一些明显的东西,要么有一些关于表单和文件我不知道的东西,而 Inertia.js 文档认为这是理所当然的。

reactjs forms inertiajs
1个回答
0
投票
  • 避免在
    value={data.file}
    元素中使用
    <input>
  • React 中文件输入的工作方式与文本输入不同。在文件输入上设置 value 属性可能会导致问题,因为它是由浏览器而不是 React 控制的。
<input
    type="file"
    id="document_pdf"
    name="file"
    accept=".pdf,application/pdf"
    className="mt-1 block w-full"
    onChange={handleFileChange}
/>
  • 使用

    Inertia.post()
    发送带有
    FormData
    选项的
    forceFormData: true
    对象,这会告诉 Inertia 将其视为文件上传。

  • 这是通过 post 请求上传文件的最终代码块:

const { data, setData, post, progress, errors } = useForm({
    recipient: '',
    recipient_mail: '',
    sum: '',
    file: null,
    filename: '',
    type: '',
});

const handleFileChange = (e) => {
    const file = e.target.files[0];
    console.log(file);
    if (file && file.type === 'application/pdf') {
        setData('file', file);
        setData('filename', file.name);
        console.log("File attached");
    } else {
        setData('file', null);
        setData('filename', '');
        console.log("No file attached");
    }
};

const handleSubmit = (e) => {
    e.preventDefault();

    const formData = new FormData();
    formData.append('recipient', data.recipient);
    formData.append('recipient_mail', data.recipient_mail);
    formData.append('sum', data.sum);

    if (data.file) {
        formData.append('file', data.file);
    }

    // Inertia sends the request as multipart/form-data
    Inertia.post('/your-endpoint', formData, {
        forceFormData: true,
        onSuccess: () => console.log("File submitted successfully"),
        onError: (errors) => console.log(errors),
    });
};
© www.soinside.com 2019 - 2024. All rights reserved.