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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 02:46:09