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

React调用setState后let声明的FormData丢失数据,寻求更优实现方案

你遇到的问题核心是组件顶层声明的fd变量会在每次组件重渲染时被重新赋值为新的FormData实例,之前存储的内容自然就丢失了。你目前将图片存在state的方案是可行的,还有两种更简洁的实现方式:


方案1:使用useRef存储FormData实例(适配现有写法的最小改动优化)

useRef的存储值不会随组件重渲染重置,也不会触发重渲染,完全适配你需要持久化存储FormData的场景。

import { useRef } from 'react'

const [ImageUploaded, setImageUploaded] = useState('')  
const [response, setResponse] = useState(null)
const [error, setError] = useState(null)
const [loading, setLoading] = useState(false)
// 用useRef存FormData,重渲染不会重置
const fdRef = useRef(new FormData())

const onImageUpload = async (e) => {
    let file = e.target.files[0]
    // 操作ref的current属性
    fdRef.current.append('file', file)
    setImageUploaded(file.name)
}
const uploadProduct = async(e) => {
    e.preventDefault()
    setLoading(true)
    try {
        const productData = {
            productName: inputState.productName.value,
            description: inputState.description.value,
            price: inputState.price.value,
            quantity: inputState.quantity.value
        }
        const {data} = await axios.post('/api/products/new', productData)
        const response = await axios.post(`/api/upload/${data.id}`, fdRef.current, {
            headers: { 'Content-Type': `multipart/form-data` },
            onUploadProgress: (uploadState) => console.log(uploadState.loaded)
        })
        setLoading(false)
        if (response.status===200) {
            setResponse(true)
            // 提交成功后可以清空FormData,避免重复提交
            fdRef.current = new FormData()
            setImageUploaded('')
        }
    } catch (error) {
        setLoading(false)
        setError(true)
    } 
}

方案2:提交时再构建FormData(更推荐,逻辑更干净)

你已经把上传的文件存在state里了,完全不需要提前维护FormData实例,只需要在提交表单的时候,把state里的文件和其他数据一次性组装成FormData即可,不需要额外维护持久化实例,也不会出现数据丢失的问题,更符合React的状态管理逻辑。

// 新增state存储上传的文件对象
const [uploadedFile, setUploadedFile] = useState(null)
const [ImageUploaded, setImageUploaded] = useState('')  
const [response, setResponse] = useState(null)
const [error, setError] = useState(null)
const [loading, setLoading] = useState(false)

const onImageUpload = async (e) => {
    let file = e.target.files[0]
    // 只存文件对象到state,不提前处理FormData
    setUploadedFile(file)
    setImageUploaded(file.name)
}
const uploadProduct = async(e) => {
    e.preventDefault()
    setLoading(true)
    try {
        const productData = {
            productName: inputState.productName.value,
            description: inputState.description.value,
            price: inputState.price.value,
            quantity: inputState.quantity.value
        }
        const {data} = await axios.post('/api/products/new', productData)
        // 提交时才组装FormData
        const fd = new FormData()
        if (uploadedFile) {
            fd.append('file', uploadedFile)
        }
        const response = await axios.post(`/api/upload/${data.id}`, fd, {
            headers: { 'Content-Type': `multipart/form-data` },
            onUploadProgress: (uploadState) => console.log(uploadState.loaded)
        })
        setLoading(false)
        if (response.status===200) {
            setResponse(true)
            // 提交成功清空state即可
            setUploadedFile(null)
            setImageUploaded('')
        }
    } catch (error) {
        setLoading(false)
        setError(true)
    } 
}

内容的提问来源于stack exchange,提问作者Amasa Abubakar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:24:04