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

Redux Dispatch异常:含Async函数时State为空数组问题排查

Redux Dispatch异步场景下状态为空的问题

执行dispatch操作后,Redux状态中本应存储对象数组,实际却得到空数组。移除代码中的异步函数部分后,dispatch可正常工作,但保留异步函数时状态始终为空。


相关代码

主逻辑代码

if(printDrawingsRedux.imagesCounter.length === 0) {
    // 创建用于统计图片占位块数量的数组    
      
    const arrNew = fd.map((value, index) => {            
        let result    
        return result = {...value, id: index, link: false, quantity: 1,
                                                              type: value.type,
                                                              name: value.name,                                                                     
                                                              blackWhitewRateCost: 50,
                                                              colorRateCost: 100,
                                                              drawingPages: [],        
                                                              currentNumberPage: 1,
                                                              howManyPages: function () {
                                                                return this.drawingPages.length
                                                              },
                                                              modalPlusSize: false, 
        }
    })
        
    dispatch(setImageCounterDrawingsRedux(arrNew))
    console.log(printDrawingsRedux.imagesCounter) 
    
}else{   
    const arrNew = fd.map((value, index) => { 
           
        let result    
        return result = {...value, id: index, link: false, quantity: 1,
                                                              type: value.type,
                                                              name: value.name,
                                                              blackWhitewRateCost: 50,
                                                              colorRateCost: 100,
                                                              drawingPages: [],        
                                                              currentNumberPage: 1,
                                                              howManyPages: function () {
                                                                return this.drawingPages.length
                                                              },
                                                              modalPlusSize: false,
        }
    })
    
    let newState = [...printDrawingsRedux.imagesCounter, ...arrNew]      
   
    let arrNew2 = newState.map((value, index) => {
        return {...value} = {...value, id: index}
    })
    dispatch(setImageCounterDrawingsRedux(arrNew2))        
}


// 遍历创建好的数组填充内容

const promiseArrayBuffer = (file) => new Promise((resolve) => {
    var fileReader = new FileReader();
    fileReader.onloadend = (e) => resolve(e.target.result);
    fileReader.readAsArrayBuffer(file);
});
    
(async function () {
    for (let i = 0; i < fd.length; i++) {
        console.log("Hello2")
        if (fd[i].type === "image/jpeg" || fd[i].type === "image/jpg" || fd[i].type === "image/png" ){        
            console.log("Hello3")
            const arrayBuffer = await promiseArrayBuffer(fd[i]);
            var image = arrayBufferToBlob(arrayBuffer, fd[i].type)         
            
            var url = URL.createObjectURL(image);
            
               
            let arrNew = printDrawingsRedux.imagesCounter.map((value, index) => {
                if (index === i) {
                    return {...value} = {...value, link: url, drawingPages: {drawingSize: "А3 (297х420мм)",
                                                        kindPrintDrawing: "чорно-білий друк",
                                                        thicknessPaperDrawing: "80 г/щ",
                                                        commentForPage: "",
                                                        quantityDrawing: 1,
                                                        personalSize1: 0,
                                                        personalSize2: 0,
                                                        quantity: 1,
                                                        pageNotToPrint: false,
                                                        personalSizeCounter: function () {
                                                        return this.personalSize1 * this.personalSize2 / 1000000
                                                        },
                                                    } }
                }else{
                    return value
                }
            })                  
            dispatch(setImageCounterDrawingsRedux(arrNew))

        }else {
            console.log("pdf catched")
        }       
    }})();

预期状态结构

{
    id: index, 
    link: false, 
    quantity: 1,
    type: value.type,
    name: value.name,
    blackWhitewRateCost: 50,
    colorRateCost: 100,
    drawingPages: [],        
    currentNumberPage: 1,
    howManyPages: function () {
        return this.drawingPages.length
    },
    modalPlusSize: false
}

Action代码

export const setImageCounterDrawingsRedux = (files) => {
    
    return {
        type: SET_IMAGECOUNTER_ASYNC_DRAWING,    
        payload: files, 
    }
}

Reducer代码

case SET_IMAGECOUNTER_ASYNC_DRAWING:   
    return {...state, printDrawings: {...state.printDrawings, imagesCounter: action.payload} }

问题原因及解决办法

1. 异步函数捕获旧状态快照

Redux通过useSelector返回的是状态快照,异步函数执行时会捕获初始的空数组状态,后续dispatch更新状态后,异步函数内的printDrawingsRedux不会自动更新,导致基于它生成的数组为空,覆盖之前的正确状态。

解决:
把初始生成的数组保存到本地变量,异步操作基于该变量修改,不依赖Redux状态:

// 先保存初始数组到本地变量
let initialImages = [];
if(printDrawingsRedux.imagesCounter.length === 0) {
    initialImages = fd.map((value, index) => ({
        ...value, 
        id: index, 
        link: false, 
        quantity: 1,
        type: value.type,
        name: value.name,                                                                     
        blackWhitewRateCost: 50,
        colorRateCost: 100,
        drawingPages: [],        
        currentNumberPage: 1,
        howManyPages: function () { return this.drawingPages.length },
        modalPlusSize: false
    }))
    dispatch(setImageCounterDrawingsRedux(initialImages))
}else{
    const arrNew = fd.map((value, index) => ({
        ...value, 
        id: index, 
        link: false, 
        quantity: 1,
        type: value.type,
        name: value.name,
        blackWhitewRateCost: 50,
        colorRateCost: 100,
        drawingPages: [],        
        currentNumberPage: 1,
        howManyPages: function () { return this.drawingPages.length },
        modalPlusSize: false
    }))
    initialImages = [...printDrawingsRedux.imagesCounter, ...arrNew].map((val, idx) => ({...val, id: idx}))
    dispatch(setImageCounterDrawingsRedux(initialImages))
}

// 异步操作基于本地变量处理
(async function () {
    let updatedImages = [...initialImages];
    for (let i = 0; i < fd.length; i++) {
        if (fd[i].type.match(/image\/(jpeg|jpg|png)/)) {        
            const arrayBuffer = await promiseArrayBuffer(fd[i]);
            const image = arrayBufferToBlob(arrayBuffer, fd[i].type)         
            const url = URL.createObjectURL(image);
            
            updatedImages[i] = {
                ...updatedImages[i],
                link: url,
                drawingPages: {
                    drawingSize: "А3 (297х420мм)",
                    kindPrintDrawing: "чорно-білий друк",
                    thicknessPaperDrawing: "80 г/щ",
                    commentForPage: "",
                    quantityDrawing: 1,
                    personalSize1: 0,
                    personalSize2: 0,
                    quantity: 1,
                    pageNotToPrint: false,
                    personalSizeCounter: function () {
                        return this.personalSize1 * this.personalSize2 / 1000000
                    }
                }
            }
        }
    }
    // 所有异步操作完成后一次性更新状态
    dispatch(setImageCounterDrawingsRedux(updatedImages))
})();

2. 语法错误导致状态异常

arrNew2的map函数中,return {...value} = {...value, id: index}是无效语法,会返回undefined,导致dispatch后状态被设为undefined,后续异步读取到空数组。

解决:修正为正确的对象展开写法:

let arrNew2 = newState.map((value, index) => {
    return {...value, id: index}
})

3. 循环中频繁dispatch导致状态覆盖

循环内每次dispatch都会覆盖整个数组,可能出现状态更新冲突。改为所有异步操作完成后一次性dispatch,减少状态更新次数,避免覆盖问题。


内容的提问来源于stack exchange,提问作者Tymokhovcev Valeriy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:20:36