在Next.js中使用Server Actions时无法将额外数据合并到FormData
解决Next.js中UploadThing图片链接加入FormData的问题
这里给你两种简单的实现方式,直接改代码就能用:
方法一:用隐藏输入框自动携带(推荐)
利用原生表单特性,把图片链接存在状态里,再绑定到一个隐藏输入框,提交表单时这个字段会自动加入FormData。
修改后的完整代码:
'use client' import { useState } from 'react'; // 新增导入useState import { Input } from "@/components/ui/input" import { CldUploadButton } from 'next-cloudinary'; import addUser from "@/components/actions/addUser"; import "@uploadthing/react/styles.css"; import { UploadButton } from "@/utils/uploadthing"; export default function Page(){ const [imageUrl, setImageUrl] = useState(''); // 新增状态存储图片链接 return( <form className="flex flex-col items-center" action={addUser}> <div className='flex flex-col justify-center align-middle gap-4'> <Input className="w-[200px]" type="text" name="name" placeholder="name" /> <Input className="w-[200px]" type="text" name="login" placeholder="login" required /> <Input className="w-[200px]" type="text" name="elo" defaultValue={1000} /> {/* 新增隐藏输入框,绑定图片链接状态 */} <Input type="hidden" name="imageUrl" value={imageUrl} /> </div> <UploadButton endpoint="imageUploader" onClientUploadComplete={(res) => { // 更新状态,把上传后的图片链接存起来 if (res?.[0]?.fileUrl) { setImageUrl(res[0].fileUrl); } }} onUploadError={(error: Error) => { alert(`ERROR! ${error.message}`); }} /> <button className="" type="submit">Submit </button> </form> ) }
之后你的addUser Server Action里,就能通过formData.get('imageUrl')拿到这个图片链接了。
方法二:手动构建FormData提交
如果不想用隐藏输入框,也可以手动拦截表单提交事件,自己构建FormData并添加图片链接:
'use client' import { useState } from 'react'; import { Input } from "@/components/ui/input" import { CldUploadButton } from 'next-cloudinary'; import addUser from "@/components/actions/addUser"; import "@uploadthing/react/styles.css"; import { UploadButton } from "@/utils/uploadthing"; export default function Page(){ const [imageUrl, setImageUrl] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); // 基于表单元素创建FormData const formData = new FormData(e.currentTarget); // 把图片链接加入FormData if (imageUrl) { formData.append('imageUrl', imageUrl); } // 调用Server Action await addUser(formData); }; return( <form className="flex flex-col items-center" onSubmit={handleSubmit}> <div className='flex flex-col justify-center align-middle gap-4'> <Input className="w-[200px]" type="text" name="name" placeholder="name" /> <Input className="w-[200px]" type="text" name="login" placeholder="login" required /> <Input className="w-[200px]" type="text" name="elo" defaultValue={1000} /> </div> <UploadButton endpoint="imageUploader" onClientUploadComplete={(res) => { if (res?.[0]?.fileUrl) { setImageUrl(res[0].fileUrl); } }} onUploadError={(error: Error) => { alert(`ERROR! ${error.message}`); }} /> <button className="" type="submit">Submit </button> </form> ) }
两种方法都能解决问题,第一种更贴合原生表单的使用习惯,推荐优先用。
内容的提问来源于stack exchange,提问作者xSwampy
相关产品推荐
相关产品推荐

