为了账号安全,请及时绑定邮箱和手机立即绑定

不可变地更新 Redux 状态

不可变地更新 Redux 状态

繁星淼淼 2023-04-27 10:50:09
我正在一成不变地改变状态,但这不起作用。基本上,我创建了一个函数来获取 excel 文件数据。此功能完美运行,但当我更新状态时,状态未更新。任何想法或任何建议与我分享这是我的状态:tableData: [], productsData: []这是状态更新的减速器:case actionTypes.READ_EXCEL:            var excel1 = [];            var excel2 = [];            const promise = new Promise((resolve, reject) => {                const fileReader = new FileReader();                fileReader.readAsArrayBuffer(action.payload);                fileReader.onload = (e) => {                    const bufferArray = e.target.result;                    const wb = { SheetNames:[], Sheets:{} };                    const ws1 = XLSX.read(bufferArray, {type: "buffer"}).Sheets.Sheet1;                    const ws2 = XLSX.read(bufferArray, {type: "buffer"}).Sheets.Sheet2;                    wb.SheetNames.push("Sheet1");                    wb.Sheets["Sheet1"] = ws1;                                        wb.SheetNames.push("Sheet2");                    wb.Sheets["Sheet2"] = ws2;                    const data1 = XLSX.utils.sheet_to_json(ws1);                    const data2 = XLSX.utils.sheet_to_json(ws2);                    resolve([ data1, data2 ]);                }                fileReader.onerror = (error) => {                    reject(error);                };            })            promise.then((excelData) => {                excel1 = excelData[0];                excel2 = excelData[1];                            });            return {                ...state,                tableData: excel1,                productsData: excel2                }        default:    }    return state; }在获取状态值和状态值未更新的 UI 中:const mapStateToProps = (state) => { return {  items: state.tableData,     <---  products: state.productsData    <--- };}
查看完整描述

2 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

新状态不会改变,因为你的 Promise 在 return 语句之后解析,这是因为 Promise 的性质,它不会阻止你的函数的执行,我建议使用像 redux-thunk 这样的中间件来实现异步逻辑在您的示例阅读文件中。最后,您将 excel 数据传递给 reducer 以更新商店。



查看完整回答
反对 回复 2023-04-27
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

由于承诺是异步的,因此首先执行返回语句,然后将数据加载到 excel1 和 excel2 中。


case actionTypes.READ_EXCEL:

            var excel1 = [];

            var excel2 = [];

            /*Below line will create a promise, which will be executed asynchronously. 

            So the execution will not wait until promise is executed.

            It will go to next line which is Promise.then()*/ 


            const promise = new Promise((resolve, reject) => {

                const fileReader = new FileReader();

                fileReader.readAsArrayBuffer(action.payload);

                fileReader.onload = (e) => {

                    const bufferArray = e.target.result;

                    const wb = { SheetNames:[], Sheets:{} };

                    const ws1 = XLSX.read(bufferArray, {type: "buffer"}).Sheets.Sheet1;

                    const ws2 = XLSX.read(bufferArray, {type: "buffer"}).Sheets.Sheet2;


                    wb.SheetNames.push("Sheet1");

                    wb.Sheets["Sheet1"] = ws1;

                    

                    wb.SheetNames.push("Sheet2");

                    wb.Sheets["Sheet2"] = ws2;


                    const data1 = XLSX.utils.sheet_to_json(ws1);

                    const data2 = XLSX.utils.sheet_to_json(ws2);

                    resolve([ data1, data2 ]);

                }

                fileReader.onerror = (error) => {

                    reject(error);

                };

            })

           /*here as well the we're just attaching a callback to promise to be executed after promise is fulfilled. so execution will attach the specified callback (excelData arrow function) to promise.then(). 

           And then execution will move to next line which is return statement.*/ 

            promise.then((excelData) => {

                excel1 = excelData[0];

                excel2 = excelData[1];

                

            });

             /*Now here, as the promises are async and will be executed after the fileReader reads data, the values of excel1 and excel2 are not updated but only contain the empty array. 

            And hence your state will have empty arrays in it*/

            return {

                ...state,

                tableData: excel1,

                productsData: excel2

                }

        default:

    }

    return state; 

}


您可以做一件事,将使用 fileReader 读取数据的代码编写到一个函数中,该函数将在您当前在代码中放置 dispatch 语句的位置执行。在 promise.then() 中,您可以使用加载的数据调用 dispatch 。所以你的新代码可能看起来像这样


// separate function for reading the data

function readExcel(excelData) {

    return dispatch=>{

    const promise = new Promise((resolve, reject) => {

        const fileReader = new FileReader();

        fileReader.readAsArrayBuffer(excelData);

        fileReader.onload = (e) => {

            const bufferArray = e.target.result;

            const wb = {

                SheetNames: [],

                Sheets: {}

            };

            const ws1 = XLSX.read(bufferArray, {

                type: "buffer"

            }).Sheets.Sheet1;

            const ws2 = XLSX.read(bufferArray, {

                type: "buffer"

            }).Sheets.Sheet2;


            wb.SheetNames.push("Sheet1");

            wb.Sheets["Sheet1"] = ws1;


            wb.SheetNames.push("Sheet2");

            wb.Sheets["Sheet2"] = ws2;


            const data1 = XLSX.utils.sheet_to_json(ws1);

            const data2 = XLSX.utils.sheet_to_json(ws2);

            resolve([data1, data2]);

        }

        fileReader.onerror = (error) => {

            reject(error);

        };

    })

    promise.then((excelData) => {

        excel1 = excelData[0];

        excel2 = excelData[1];

        // Dispatching only after we get the data from fileReader

        dispatch({

            type: actionTypes.READ_EXCEL,

            payload: {

                excel1,

                excel2

            }

        })

      });

   }

}


// In reducer function

case actionTypes.READ_EXCEL:

    return {

        ...state,

        tableData: action.payload.excel1,

        productsData: action.payload.excel2

    }


查看完整回答
反对 回复 2023-04-27
  • 2 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信