React Hook Form+Next.js14 Server Actions文件上传报错求助
Next.js 14 + React Hook Form 文件上传Server Actions报错解决办法
问题重现
使用React Hook Form注册文件输入框后,选择文件提交时触发如下错误:
Uncaught Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.
不选择文件时流程正常,但尝试构造新FormData传递文件时,Server Action仅收到空FileList数组,无法完成上传。
解决步骤
1. 客户端手动构建原生FormData
不要直接把React Hook Form处理后的表单数据传给Server Action,而是手动创建原生FormData,提取文件后再传递:
"use client" import { useForm } from "react-hook-form"; export default function ProfileForm() { const { register, handleSubmit, getValues } = useForm(); const onSubmit = async () => { const formData = new FormData(); // RHF中文件输入返回的是File数组,取第一个元素 const avatarFile = getValues("avatar_url")?.[0]; if (avatarFile) { formData.append("avatar_url", avatarFile); } // 调用Server Action await updateUserProfile(formData); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register("avatar_url")} type="file" name="avatar_url" accept="image/*" /> <button type="submit">upload</button> </form> ); }
2. Server Action接收原生FormData处理上传
在Server Action中直接从FormData获取文件,调用Supabase Storage API完成上传:
"use server" import { supabase } from "@/lib/supabase"; export async function updateUserProfile(formData) { const file = formData.get("avatar_url"); if (!file) return; // 替换为你的Supabase存储桶名称和自定义文件路径规则 const { data, error } = await supabase.storage .from("avatars") .upload(`user-assets/${file.name}`, file, { cacheControl: "3600", upsert: true // 若文件已存在则覆盖 }); if (error) { throw error; } // 可选:获取文件公开链接并更新用户资料 const { data: publicUrlData } = supabase.storage .from("avatars") .getPublicUrl(data.path); // 此处可添加更新用户表的逻辑 // await supabase.from("users").update({ avatar_url: publicUrlData.publicUrl }).eq("id", 当前用户ID); return publicUrlData; }
原因说明
React Hook Form的handleSubmit默认会把表单数据转换成包含FileList的对象,而Server Action不支持传递FileList这类非普通对象。手动构建原生FormData并传递,就能避开这个限制,让文件正确到达Server Action。
内容的提问来源于stack exchange,提问作者RJT
相关产品推荐
相关产品推荐

