简体   繁体   English

更新Redux存储中数组中的嵌套对象

[英]Update nested object in array in a redux store

So I've been struggling to find the best practice on this, changing the store without mutating the store directly. 因此,我一直在努力寻找最佳实践,在不直接改变商店的情况下更换商店。 Especially when it is nested. 特别是当它嵌套时。

I've seen some great articles about this but I'm still not able to figure out how to get this perfect in my scenario. 我已经看过一些很棒的文章,但是我仍然无法弄清楚如何在我的场景中做到这一点。 ( https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns ) https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns

In my case, I have a proposals store with records and each record ( proposal ) contains a checklist which is an array that looks like this: 就我而言,我有一个包含recordsproposals存储,每个记录( proposal )都包含一个checklistchecklist是一个像这样的数组:

checklist: [
    {
      label: 'lease_sign',
      done: false
    }
],

I want to change done to true . 我想将done更改为true Now I have this action being triggered by my WebSocket: 现在,我的WebSocket触发了此操作:

case CHECK_TODO_ITEM: {
    const { data } = action;

    // find match record
    const proposal = _.find(state.records, ['uuid', data.proposal]);
    // find match check
    const check = _.find(proposal.checklist, ['label', data.item]);
    // change check to true
    check.done = true;

    // find index of propsal in the current state
    const index = _.findIndex(state.records, (p) => p.uuid === data.proposal);

    // re-asign state
    return _.assign({}, state, {
        records: _.assign({}, state.records, {
            [index]: proposal,
        }),
    });
}

I've also tried with: 我也尝试过:

return {
    ...state,
        records: {
            ...state.records,
            [index]: {
                ...state.records[index],
                checklist,
            }
        }
    }
};

But this is still mutating the state off-course. 但这仍然使国家偏离了路线。 I can't figure out what the perfect way to do this is. 我不知道什么是完美的方法。

If someone could help me out that would be great! 如果有人可以帮助我,那就太好了!

For me, the best library for update an immutable state is immutability-helper . 对我来说,更新不可变状态的最佳库是immutability-helper

With this one, you could do something like this (idk if it works but you have the idea): 有了这个,您可以执行以下操作(如果可行,可以执行idk,但您有想法):

case CHECK_TODO_ITEM: {
  const index = 8; // random record index
  const index2 = 3; // random item index
  return update(state, {
    records: {      
      [index]: {
        checklist: {
          [index2]: {
            $merge: {
              done: true,
            },
          },
        },
      },
    },
  });
}

Just use map as below and spread operator for the object. 只需使用下面的map并为该对象传播运算符。 Both map and ... are immutable operations. map...都是不可变的操作。

 const checklist = [ { id: 1, done: false }, { id: 2, done: false }, { id: 3, done: false } ] const setDone = id => checklist.map(item => ( id === item.id ? {...item, done: true } : item )) console.log(setDone(2)); 

For checklist items use some dynamically generated unique id and refer to the corresponding state item with this id on toggle. 对于清单项目,请使用一些动态生成的唯一ID,并在切换时使用此ID引用相应的状态项目。

Objects are assigned by reference in ECMAScript, not by value . 对象是通过ECMAScript中的引用分配的,而不是通过value分配的。

By using underscore's find method, your proposal and check variables will still reference the objects in de Redux store, which you then modify directly. 通过使用下划线的find方法, proposalcheck变量仍将引用de Redux存储中的对象,然后直接对其进行修改。 What you want to do is "clone" the state, or part of the state you need, at the moment your action triggers the reducer. 您要做的是在您的动作触发化简器的那一刻“克隆”状态或所需状态的一部分。 There's multiple methods of achieving a clone: 有多种实现克隆的方法:

  • spread operator: newState = {...state} 传播算子: newState = {...state}
  • newState = JSON.parse(JSON.stringify(state))
  • using lodash (since you are already using it): newState = _.cloneDeep(state) 使用lodash(因为您已经在使用它): newState = _.cloneDeep(state)

This new state can then be modified, and subsequently be set to the store. 然后可以修改此新状态,然后将其设置为存储。

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

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