【问题标题】:How to change the State in React Redux without mutating data?如何在不改变数据的情况下更改 React Redux 中的状态?
【发布时间】:2018-10-29 20:21:50
【问题描述】:

我知道“神圣”数据是什么以及如果处理不当可能会变得多么危险;这就是为什么在我的应用程序中,我现在处于需要处理嵌套的长 JSON 对象(代表我的应用程序状态)的位置,并且进出需要的节点/值已经让我很头疼进行修改。我正在考虑包括Immutable.js。现在的问题是:我如何调整我的减速器、动作、状态等?

这是来自MongoDB 数据库的我的状态摘录:

"shops": [
        {
            "shopId": "5a0c67e9fd3eb67969316cff",
            "picture": "http://placehold.it/150x150",
            "name": "Zipak",
            "email": "leilaware@zipak.com",
            "city": "Rabat",
            "location": {
                "type": "Point",
                "coordinates": [
                    -6.74736,
                    33.81514
                ]
            }
        },
        {
            "shopId": "5a0c6b55fd3eb67969316d9d",
            "picture": "http://placehold.it/150x150",
            "name": "Genekom",
            "email": "leilaware@genekom.com",
            "city": "Rabat",
            "location": {
                "type": "Point",
                "coordinates": [
                    -6.74695,
                    33.81594
                ]
            }
        },
        ...

当某个动作(最终用户点击“Like”按钮)被触发时,我需要为相关的Shop对象添加一个属性,所以它会变成这样:

{
    "shopId": "5a0c67e9fd3eb67969316cff",
    "picture": "http://placehold.it/150x150",
    "name": "Zipak",
    "email": "leilaware@zipak.com",
    "city": "Rabat",
    "liked": true,
    "location": {
        "type": "Point",
        "coordinates": [
            -6.74736,
            33.81514
        ]
    }
},

现在,我设法将 liked 属性添加到单个 Shop 对象,但是当我想更改/修改状态(所有 Shop 对象的组)时,我得到了重复的对象(新的一个具有liked 属性和旧属性)。为了避免这种混乱,我想使用Immutable.js 来处理这些操作,以确保一切都干净且正确。

我从哪里开始?我是否将状态转换为Immutable.js 地图?列表?

【问题讨论】:

    标签: javascript reactjs redux immutable.js


    【解决方案1】:

    您可以使用immutability-helper 而不是使用Immutable.js,它有一个update 函数返回更新后的值而不改变原始值。

    immutability-helper 的语法灵感来自 MongoDB,因此习惯它对您来说应该不会很难。

    对于您的情况,您可以使用以下示例修改您的状态,

    import update from 'immutability-helper';
    
    const id = '5a0c67e9fd3eb67969316cff'; // id of the item you need to update
    const newState = update(state, {
      shops: {
        $apply: (item) => {
          if (item.shopId !== id) return item
          return {
            ...item,
            liked: true
          }
        }
      }
    });
    

    【讨论】:

      【解决方案2】:

      只需将已识别商店的数组减少为获取成功的对象。对任何唯一项列表执行此操作是一个很好的做法,以避免查找函数的 O(n) 复杂性并以更简单的方式改变您的状态。

      在您的商店减速器中减少商店获取成功:

      shops.reduce((obj, item) => {
          obj[item.id] = item
              return obj;
      }, {})
      

      这样就可以很容易地在你的商店减速器中操作你的对象,比如成功:

      return { 
          ...state, 
         [action.shopId]: { 
             ...state[action.shopId], 
             liked: true,
          },
      }
      

      【讨论】:

      • 它将商店数组 [{ id: 1, name: 'A' }, { id: 2, name: 'B' }] 变成一个对象 { 1: { id: 1,名称:'A'},2:{ id:2,名称:'B'}}。
      • 您还需要使用 Object.values(state.shops) 将 redux 状态映射到组件的 props 而不是直接传递它。
      猜你喜欢
      • 2016-12-24
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 2017-07-20
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      • 2020-02-01
      相关资源
      最近更新 更多