更新redux中深度嵌套的状态对象,不使用spread运算符

qybjjes1  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(189)

我已经为此头疼了一个星期了!!
我的redux状态如下所示

{
  data: {
      chunk_1: {
        deep: {
         message: "Hi"
        }
      },
      chunk_2: {
        something: {
         something_else: {...}
        }
      },
     ... + more
  },
  meta: {
   session: {...},
   loading: true (or false)
  }
}

我有一个键数组,比如["path", "to", "node"]和一些data,在action.payload中,我的深度嵌套状态对象的最后一个节点应该被替换为这些键。
显然我不能使用spread操作符,如文档中所示(因为我的keys数组是动态的,可以改变值和长度)。我已经尝试过使用Immutable.js,但没有成功。下面是我的代码

// Importing modules ------ 
import {fromJS} from "immutable";

// Initializing State --------- 
const InitialState = fromJS({ // Immutable.Map() doesn't work either
    data: { ... },
    meta: {
        session: {
            user: {},
        },
        loading: false,
        error: "",
    },
});

// Redux Root Reducer ------------
function StoreReducer(state = InitialState, action) {

  switch (action.type) {
    case START_LOADING: 
    return state.setIn(["meta"], (x) => {
                return { ...x, loading: true };
    });

    case ADD_DATA: {
      const keys = action.payload.keys; // This is a valid array of keys
      return state.updateIn(keys, () => action.payload); // setIn doesn't work either
    }

}

我得到的错误..

Uncaught TypeError: state.setIn (or state.updateIn) is not a function
    at StoreReducer (reducers.js:33:1)
    at k (<anonymous>:2235:16)
    at D (<anonymous>:2251:13)
    at <anonymous>:2464:20
    at Object.dispatch (redux.js:288:1)
    at e (<anonymous>:2494:20)
    at serializableStateInvariantMiddleware.ts:172:1
    at index.js:20:1
    at Object.dispatch (immutableStateInvariantMiddleware.ts:258:1)
    at Object.dispatch (<anonymous>:3665:80)

"我想要什么"
用包含键的数组更新redux状态(深度嵌套对象)的正确方法。

gpnt7bae

gpnt7bae1#

请注意,您使用的Redux风格非常过时。自2019年以来,我们不建议您使用手写的switch..case reducer或immutable库。相反,您应该使用官方的Redux Toolkit with createSlice,它允许您在case reducer中编写变异逻辑(因此也可以使用任何helper库,如果您想使用的话)。
请阅读Why Redux Toolkit is how to use Redux today

e0uiprwp

e0uiprwp2#

您可以使用类似以下内容:

import { merge, set } from 'lodash';

    export default createReducer(initialState, {
...
      [updateSettingsByPath]: (state, action) => {
        const {
          payload: { path, value },
        } = action;
        const newState = merge({}, state);
        set(newState, path, value);
        return newState;   },
...}

相关问题