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

Post请求成功后实时刷新GetAssets数据的问题及替代方案咨询

问题概述

我有三个API:GetAssets、assetsOptionsList 和 getAssetsLibrary。需求是向 getAssetsLibrary 发送POST请求提交数据后,GetAssets 接口能实时展示新增的数据。目前功能整体正常,但实时展示有问题:我通过设置 runTime 状态为 true 触发刷新,但这种方式仅首次生效,后续无法实现实时更新。希望找到可行的替代方案,同时要求在POST请求成功时调用获取资产的 one 函数。

现有代码

const [images, setImages] = useState([]);
const [assetOptions, setAssetOptions] = useState([]);
const [faqOpened, setToggleFaq] = useState(false);
const [runTime, setRunTime] = useState(false)
const [assetID, setAssetID] = useState()
const [isLoading, setIsLoading] = useState(false);

const handleForm = (e) => {
    const index = e.target.selectedIndex;
    const el = e.target.childNodes[index]
    const option = el.getAttribute('id');
    setAssetID(option)
}

const formHandler = (e) => {
    e.preventDefault()
    let formData = new FormData();
    formData.append('media', e.target.media.files[0]);
    formData.append('assetListId', assetID)
    formData.append('name', e.target.name.value);
    console.log(Object.fromEntries(formData))

    const res = axios.post('api/asset-library',
        formData
    ).then((response) => {
        showSuccessToaster(response?.data?.message)
        setRunTime(true)
        setToggleFaq(false)
    })
    .catch((error) => {
        showErrorToaster(error?.response?.data?.message)
    })
}

const showSuccessToaster = (response) => {
    return uploadToasterSuccess.show({ message: response });
}

const showErrorToaster = (error) => {
    return uploadToasterError.show({ message: error });
}

const one = async () => {
    setIsLoading(true) 
    const data = await axios.get('api/assets').then((res) => {
        return res?.data?.data
    })
    setImages(data)
    setIsLoading(false)
}

const two = async () => {
    const data = await axios.get('/api/asset-list').then((res) => {
        return res?.data?.data
    })
    setAssetOptions(data)
}

useEffect(() => {
    one()
    two()
}, [runTime]);
解决方案

方案1:POST成功后直接调用刷新函数

这是最直接有效的方式,不需要依赖状态触发。在POST请求的成功回调里直接调用one(),因为新增资产后assetOptions(下拉选项列表)通常不会变化,所以可以只刷新资产列表,不用每次都调用two()。

修改后的formHandler代码:

const formHandler = (e) => {
    e.preventDefault()
    let formData = new FormData();
    formData.append('media', e.target.media.files[0]);
    formData.append('assetListId', assetID)
    formData.append('name', e.target.name.value);
    console.log(Object.fromEntries(formData))

    axios.post('api/asset-library', formData)
    .then((response) => {
        showSuccessToaster(response?.data?.message)
        setToggleFaq(false)
        // 直接调用获取资产的函数,实现实时刷新
        one()
    })
    .catch((error) => {
        showErrorToaster(error?.response?.data?.message)
    })
}

同时可以删掉冗余的runTime状态和相关依赖,简化初始化逻辑:

// 移除runTime状态
// const [runTime, setRunTime] = useState(false)

// 仅在组件挂载时初始化数据
useEffect(() => {
    one()
    two()
}, []);

方案2:修复原状态触发逻辑(如果一定要用状态驱动)

原方案失效的原因是runTime设为true后,后续再设true不会触发状态变更(因为值没有变化)。可以改成用计数器或者切换布尔值的方式:

// 把runTime换成计数器
const [refreshCount, setRefreshCount] = useState(0)

// POST成功时递增计数器,触发状态变更
const formHandler = (e) => {
    // ... 其他代码
    axios.post('api/asset-library', formData)
    .then((response) => {
        showSuccessToaster(response?.data?.message)
        setToggleFaq(false)
        setRefreshCount(prev => prev + 1)
    })
    // ... 错误处理
}

// useEffect依赖refreshCount,每次计数器变化就刷新数据
useEffect(() => {
    one()
    two()
}, [refreshCount]);

方案3:利用POST返回数据直接更新本地状态

如果getAssetsLibrary接口会返回新增的资产完整数据,可以不用重新调用GetAssets接口,直接把新增数据加到本地images数组里,减少一次网络请求,提升性能:

const formHandler = (e) => {
    // ... 其他代码
    axios.post('api/asset-library', formData)
    .then((response) => {
        showSuccessToaster(response?.data?.message)
        setToggleFaq(false)
        // 假设response.data.data是新增的资产对象,直接追加到本地列表
        setImages(prevImages => [...prevImages, response.data.data])
    })
    // ... 错误处理
}

内容的提问来源于stack exchange,提问作者David-JSON

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:40:32