Inertia React文章更新时上传文件触发必填字段验证错误
文章更新功能上传文件时必填字段验证失败问题解决
问题描述
开发文章更新功能时,仅修改标题或正文提交表单无异常,但上传缩略图并提交时,明明已填写标题和正文,却触发必填字段验证错误:
标题字段是必填的。
内容字段是必填的。
相关代码
Laravel ArticleController 代码
public function update(Request $request, Article $article) { $request->validate([ 'title' => 'required', 'body' => 'required', 'thumbnail' => 'nullable|mimes:png,jpg,jpeg', ]); // 上传新缩略图时的处理 if ($request->hasFile('thumbnail')) { $thumbnail = $request->file('thumbnail')->store('thumbnail'); $article->update([ 'title' => $request->title, 'body' => $request->body, 'thumbnail' => $thumbnail ]); } else { // 无新缩略图时的处理 $article->update([ 'title' => $request->title, 'body' => $request->body, ]); } return redirect('/admin'); }
Inertia React 视图代码
import React, { useState } from "react"; import Navbar from "../components/Navbar"; import { Editor } from "@tinymce/tinymce-react"; import { useForm } from "@inertiajs/inertia-react"; export default function EditArticle({ article }) { const { data, setData, patch, errors, reset, processing } = useForm({ title: article.title, body: article.body, thumbnail: null }); const [isOpen, setIsOpen] = useState(false); function onSubmitEventHandler(e) { e.preventDefault(); patch(`/articles/${article.id}/edit`, { onSuccess: () => reset() }); } function openModalEventHandler() { setIsOpen(!isOpen); } function handleThumbnailChange(e) { setData('thumbnail', e.target.files[0]); } return ( <> <Navbar /> <form className="mt-24" onSubmit={onSubmitEventHandler} encType="multipart/form-data"> { isOpen && <> <div className="fixed inset-0 flex items-center justify-center z-40"> <div className="p-4 rounded-lg flex flex-col bg-white text-black z-50 relative"> <div onClick={openModalEventHandler} className="hover:cursor-pointer absolute -top-2 -right-2 shadow-md p-2 bg-white rounded-full"> <img src="/icon/closeIcon.svg" className="w-4" alt="关闭图标" /> </div> <h2 className="text-2xl font-semibold">编辑文章</h2> <label htmlFor="title" className="mt-5 text-sm">标题:</label> <input type="text" id="title" className="rounded-lg border py-2 px-3" value={data.title} onChange={(e) => setData('title', e.target.value)} /> <label htmlFor="thumbnail" className="mt-5 text-sm">缩略图:</label> <input type="file" className="mt-2" id="thumbnail" onChange={handleThumbnailChange} /> <button type="submit" disabled={processing} className={`mt-4 py-2 px-4 bg-darkerBlue rounded-lg text-white ${processing && 'opacity-25'}`}>保存文章</button> {errors.title && <p className="mt-2 text-sm text-red-700">{errors.title}</p> } {errors.body && <p className="mt-2 text-sm text-red-700">{errors.body}</p> } {errors.thumbnail && <p className="mt-2 text-sm text-red-700">{errors.thumbnail}</p> } </div> <div onClick={openModalEventHandler} className="fixed inset-0 bg-black opacity-35"></div> </div> </> } <Editor apiKey='5d3gmavobfl1gplfh7eithg9chuj3shiru72msgp1kescjzi' init={{ toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | table | addcomment showcomments | align lineheight | checklist numlist bullist indent outdent | charmap | removeformat', height: 520, }} value={data.body} onEditorChange={(newValue, editor) => setData('body', newValue)} /> <div onClick={openModalEventHandler} className="hover:bg-gray-200 hover:cursor-pointer bg-white transition fixed right-3 bottom-5 rounded-full p-4 card-shadow"> 保存 </div> </form> </> ) }
问题原因
Inertia的patch方法默认以JSON格式提交数据,当表单包含文件时,JSON格式无法正确传递文件,同时后端无法解析常规JSON中的表单字段,导致title和body字段未被正确接收,触发必填验证失败。
解决方案
修改React组件中的提交函数,添加multipart: true选项,让Inertia自动以FormData格式提交包含文件的表单数据:
function onSubmitEventHandler(e) { e.preventDefault(); patch(`/articles/${article.id}/edit`, { onSuccess: () => reset(), multipart: true // 启用多部分表单数据提交 }); }
添加该选项后,Inertia会自动处理表单数据的格式转换,确保文件和其他字段都能被后端正确接收,从而避免必填字段的错误验证。
内容的提问来源于stack exchange,提问作者Althaf Budiman
相关产品推荐
相关产品推荐

