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

NextJS 14中FormData为空问题求助:表单数据无法存入

NextJS 14中FormData无法存入数据且打印为空的解决方案

问题根源分析

  • FormData实例声明位置错误:组件顶层声明的form会在每次重渲染时被重新创建,导致提交时操作的实例可能不是最新的,还会出现复用旧实例的问题。
  • 直接打印FormData看不到内容:FormData是特殊内置对象,直接console.log(form)只会显示空对象,必须通过遍历或转换为数组才能查看实际内容。
  • 手动设置Content-Type导致解析失败:axios发送FormData时会自动生成包含boundary的正确Content-Type,手动设置会覆盖该头,让后端无法解析数据。
  • 状态未初始化默认值:部分useState没有设置初始值,可能导致存入FormData时出现undefined无效值。

具体修复步骤

1. 移到提交函数内创建FormData实例

每次提交表单时创建全新的FormData,避免实例污染:

const handleSubmit = async (e) => {
    e.preventDefault();
    // 每次提交都生成新的FormData实例
    const form = new FormData();

    form.set('productName', productName);
    form.set('categoryID', categoryID);
    form.set('productDescription', productDescription);
    form.set('price', price);
    form.set('rating', rating);
    // 先判断文件是否存在再存入
    if (image) {
        form.set('image', image);
    }

    // 正确查看FormData内容的方式
    console.log('FormData内容:');
    for (const [key, value] of form.entries()) {
        console.log(`${key}:`, value);
    }
    // 或者转换为数组打印
    console.log(Array.from(form.entries()));

    const jwt = await GenerateJWT(productName);
    await axios.post('/api/v1/products', form, {
        headers: {
            JWT: jwt
        }
    })
    .then(data => {
        console.log(data);
        alert('Product created successful');
        router.push('/');
    })
    .catch(err => {
        console.error(`Error to create a new product -> ${JSON.stringify(err)}`);
        console.log(err);
        alert('Error to create a new product, please try again later.');
    });
};

2. 移除手动设置的Content-Type

删除axios请求中手动添加的"Content-Type": 'multipart/form-data',让axios自动处理请求头:

// 正确写法
await axios.post('/api/v1/products', form, {
    headers: {
        JWT: jwt
    }
})

3. 给状态设置初始默认值

避免状态为undefined,给所有useState设置合理的初始值:

const [productName, setProductName] = useState('');
const [categoryID, setCategoryID] = useState('');
const [productDescription, setProductDescription] = useState('');
const [price, setPrice] = useState('');
const [rating, setRating] = useState('');
const [image, setProductImg] = useState(null);

4. 可选:直接从表单元素构建FormData(简化代码)

无需手动逐个设置字段,直接用表单DOM元素生成FormData,前提是表单控件的name属性和你要传递的键名一致:

const handleSubmit = async (e) => {
    e.preventDefault();
    // 直接从表单元素创建FormData
    const form = new FormData(e.target);

    // 打印内容
    console.log(Array.from(form.entries()));

    const jwt = await GenerateJWT(productName);
    await axios.post('/api/v1/products', form, {
        headers: {
            JWT: jwt
        }
    })
    // ...后续处理逻辑
};

同步修改select的name属性为categoryID,和你要传递的键名匹配:

<select name="categoryID" id="categories" onChange={(e) => setCategoryID(e.target.value)}>
    {
        categories.length ?
            categories.map(category => (
                <option key={category.id} value={category.id}>{category.category}</option>
            ))
            : <option>Loading categories</option>
    }
</select>

验证要点

修复后提交表单时,通过遍历FormData的方式确认所有字段都已正确存入;同时检查浏览器网络请求的请求头,应该会自动生成包含boundary的multipart/form-data类型头。

内容的提问来源于stack exchange,提问作者Martín Salazar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:55:33