【问题标题】:How to immutably update/replace React Redux State with a double nested array of objects?如何用双重嵌套的对象数组不变地更新/替换 React Redux 状态?
【发布时间】:2019-06-11 02:24:15
【问题描述】:

我的 redux 状态有一个 SessionList,它是一个 SessionObjects 数组,每个 SessionObject 都有一个 HandObjects 数组。

我使用状态通过添加新的 HandObjects 来更新单个 SessionObjects,但是我想用我更新的 SessionObject 更新 redux 存储(如果可能,不可变)。

SessionList 中 SessionObject 的索引是 action.payload.Id(我想?我会展示我的 SessionObject 构造函数)

**添加会话工作得很好,我只用商店中已有的会话更新会话

我已经尝试了我能找到的每个链接,但我的代码完全不同,以至于我似乎无法正确更新我的 SessionList。

我的减速器,初始状态 store.js(我的减速器所在的位置)

const initialState = {
    SessionList: [],
}
...
case "UPDATE_SESSION":
            //action.payload is a SessionObject
            //action.payload.Id is the Id that i want to update
            // i want to set SessionList[action.payload.Id] = action.payload
            state = {
                ...state,
                SessionList : state.SessionList.map((item, index) => {
                    if (index != action.payload.id) {
                      return item
                    }

                    return action.payload
                    //This code doesn't visibly do anything that I can find
                  })

                // *******FIRST TRY*******
                // ...state,
                //  SessionList: {
                //     ...state.SessionList,
                //     SessionList[action.payload.id] : action.payload 
//syntax error, but basically what i want to do
                //      }
                // }
                // ***********************
            };
            break;

SessionObject 构造函数 会话.js

export function SessionObject(_id, _name, _hands) {
    this.id = _id, //int
    this.name = _name, //string
    this.HandList = _hands //array of HandObject objects
}
var defaultSession = new SessionObject(0, "default", []);

*如果我做错了, 我打电话 (Session.js)

this.props.navigation.state.params.updateMethod(this.state.Session); //update store

来自堆栈导航器子组件。
然后在父组件中, 我打电话 (Home.js)

UpdateSession = (session) => {
      this.props.updateSession(session);
    };

我的调度员看起来像: (Home.js)

updateSession: (session) => {
        dispatch({
          type: "UPDATE_SESSION",
          payload: session
        });
      }

通过测试,我有点确定我的减速器被正确调用了。

我想在 SessionList 的正确索引中将 SessionObject 替换为 action.payload。

编辑 *

Session.js

addItem = () => {
        this.setState((state, props) => ({
        Session : {
          ...state,
          HandList: [...state.Session.HandList, new HandObject(state.HandCount)]
        },
        HandCount : state.HandCount + 1,
        }));
        this.props.navigation.state.params.updateMethod(this.state.Session); //update store
    };

Session.js 中的状态是一个 SessionObject

【问题讨论】:

  • 您在哪里创建提供给updateSessionsession?您有可能一遍又一遍地传递相同的引用吗?即,如果您尝试使用 ``` payload: { ...session } ``` 问题仍然存在?
  • @sminutoli 我在我的问题中添加了代码,我正在更新会话。我认为我这样做的方式会创建一个新对象?就我的工作流程而言,我的主屏幕访问 redux 存储,并将 SessionList(充满 SessionObjects)放在 FlatList 中。每一个都是一个按钮,它导航到一个会话页面,该页面以相同的方式显示单个 SessionObject 的 HandObjects 列表。 Hands 被添加/更新,更新 Session.js 状态的 SessionObject,将 session 发送回 Home 屏幕,更新 redux store 的完整结构。
  • setState 不是同步调用,你不能使用 this.state.Session 期望它是全新的对象,也许你可以将这个新会话存储在一个变量上,同时传递 setStateupdateMethod 同一个对象。我不明白你为什么要混合 redux w setState。
  • SessionObject 构造函数使用小写“i”作为其id 属性,而在reducer 的UPDATE_SESSION 情况下,写入action.payload.Id(大写“I”),这将评估如undefined. 如果您登录action.payload,这就是您所看到的吗?
  • @leitdeux 很好,但这并没有改变结果

标签: javascript reactjs react-native redux react-redux


【解决方案1】:

要获得SessionList[action.payload.Id] 的结果,您需要将SessionList 初始化为对象而不是数组。然后你可以相应地更新。

   const initialState = {
      SessionList: {},
   }

   case "UPDATE_SESSION":
            state = {
                ...state,
                SessionList: Object.keys(state.SessionList).reduce((acc, id) => {
                    if (id === action.payload.Id) {
                      acc[id] = action.payload;
                    } else {
                      acc[id] = state.SessionList[id];
                    }

                    return acc;
                  }, {});
            };

更新

根据here 的要求,以下是 addupdatereplacedelete 处理程序,无需更改SessionList 到一个对象。

const initialState = {
     SessionList: [],
}

注意:action.payload(无论在哪里使用)是一个会话对象。

添加

state = {
    ...state,
    SessionList: [...state.SessionList, action.payload];
};

更新

state = {
    ...state,
    SessionList: state.SessionList.map((session) => {
        if (session.Id === action.payload.Id) {
           return Object.assign({}, session, action.payload);
        }

        return session;
    })
};

替换

state = {
    ...state,
    SessionList: state.SessionList.map((session) => {
        if (session.Id === action.payload.Id) {
           return action.payload;
        }

        return session;
    })
};

删除

state = {
    ...state,
    SessionList: state.SessionList.filter((session) => session.Id !== action.payload.Id)
};

【讨论】:

  • 对象没有.reduce,我理解你的意图,但它不准确
  • @sminutoli 你是对的。我习惯于使用lodash.reduce,它也适用于对象。请查看更新的答案。
  • @UmairSarfraz 有没有办法用数组做到这一点?我的结构不适用于 SessionList 对象。 SessionList 包含一个 SessionObjects 数组,每个 SessionObjects 都包含一个 HandObjects 数组。我需要能够在我的结构的所有级别中添加/删除/更新/替换每个相应的对象
  • @AdamWells 是的。我已经更新了我的答案。请检查。希望这能回答你的问题。如果您需要任何澄清,请随时告诉我。
  • @UmairSarfraz 这很有帮助,谢谢!但是我开始认为我的问题可能在我的应用程序的其他地方。在我的 Session.js 文件中,我正在创建 HandObjects,它应该被添加到它的 Hands 数组中的 SessionObject 中,当我导航回 Home.js 中的 SessionList,然后导航回 Session.js 文件时,我之前创建的 HandObjects 应该仍然存在,但是它会删除它们。
猜你喜欢
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-30
  • 2019-10-10
  • 1970-01-01
  • 2021-03-15
  • 2021-04-15
相关资源
最近更新 更多