简体   繁体   English

如何在React Redux中更改状态而不更改数据?

[英]How to change the State in React Redux without mutating data?

I'm aware of "sacred" data is and how dangerous it might get if handled incorrectly; 我知道“神圣”的数据是什么,如果处理不当,可能会变得多么危险。 that's why in my app, I'm in a position now where I need to handle a nested long JSON object (that repsents my app state) and it's already a headache to me to get in and out of the nodes/values that need to be amended. 这就是为什么在我的应用程序中,我现在需要处理一个嵌套的长JSON对象(代表我的应用程序状态),而进入和退出需要处理的节点/值已经让我头疼被修改。 I was thinking of including Immutable.js . 我正在考虑包括Immutable.js The question now is: how do I adapt my reducers, actions, state, etc? 现在的问题是:我该如何调整减速器,动作,状态等?

Here's an extract of my state when it comes from the MongoDB database: 这是当我来自MongoDB数据库时的状态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
                ]
            }
        },
        ...

When a certain action (end-user hits a "Like" button) is triggered, I need to add an attribute to the related Shop object, so it'd become like this: 当某个操作(最终用户点击“赞”按钮)被触发时,我需要向相关的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
        ]
    }
},

Now, I manage to add the liked attribute to the individual Shop object, but when I want to change/amend the state (group of all Shop objects), I get the object duplicated (the new one with the liked attribute and the old one). 现在,我设法将liked属性添加到单个Shop对象,但是当我想更改/修改状态(所有Shop对象的组)时,我得到了重复的对象(新的具有liked属性的对象和旧的)。 To avoid this mess, I want to handle these operations using Immutable.js to make sure everything is clean and proper. 为了避免这种混乱,我想使用Immutable.js处理这些操作,以确保所有内容都正确无误。

Where do I start from? 我从哪里开始? Do I convert the state to an Immutable.js Map? 是否将状态转换为Immutable.js地图? List? 清单?

Rather than using Immutable.js you can use immutability-helper which has an update function returns the updated value without mutating the original value. 除了使用Immutable.js您还可以使用具有update功能的immutability-helper来返回更新后的值,而无需更改原始值。

immutability-helper has a syntax inspired from MongoDB so getting used to it shouldn't be very hard for you. immutability-helper具有受MongoDB启发的语法,因此习惯它对您来说并不难。

For your case, you can modify your state with the below sample, 对于您的情况,您可以使用以下示例修改状态,

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
      }
    }
  }
});

Simply reduce your array of identified shops to an object on fetch success. 只需将成功识别的商店减少为一个对象即可。 It's a good practice to do so for any list of unique items to avoid the O(n) complexity of find functions and to mutate your state in a simpler way. 对任何唯一项列表执行此操作都是一种好习惯,以避免find函数的O(n)复杂性并以更简单的方式来改变状态。

Reduce shops on fetch success in your shops reducer : 在您的商店减速器中获取成功时减少商店:

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

It will then be easy to manipulate your object inside your shops reducer on any action such as a like success : 然后,可以通过诸如成功之类的任何操作来轻松地在商店减速器中操纵对象:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM