繁体   English   中英

如何更新或添加到immutable.js列表

[英]How to update or add to immutable.js List

我在基于React的项目(基于React Boilerplate )中使用Redux和Immutable.js,我正在寻找一种更新或添加到Immutable.js列表的惯用方法。

我目前的设置。 州最初看起来像这样:

const initialState = fromJS({
  accounts: [],
  activeAccount: null,
  loadedAccounts: [],
});

我有一个account对象的不可变记录:

const account = new Record({
  description: '',
  id: '',
  name: '',
  status: '',
});

而我的减速机:

function reducer(state = initialState, action) {
  switch (action.type) {
    case LOAD_ACCOUNT_SUCCESS:
      return state
        .set('activeAccount', new account(action.account))
    default:
      return state;
  }
}

这很好 - 当触发LOAD_ACCOUNT_SUCCESS操作时, activeAccount更新为action.account的值。

我可以修改它,以便每个新的LOAD_ACCOUNT_SUCCESS操作将新加载的帐户数据推送到loadedAccounts

function reducer(state = initialState, action) {
  switch (action.type) {
    case LOAD_ACCOUNT_SUCCESS:
      const loadedAccount = new account(action.account);
        return state
          .update('loadedAccounts', (loadedAccounts) => loadedAccounts.push(loadedAccount));
    default:
      return state;
  }
}

但是,此时加载相同的帐户数据两次将导致每次将新记录推送到我的列表(复制数据)。 我想要做的,而不是要么添加action.accountloadedAccounts (就像现在发生) 更新记录的列表,如果有匹配的ID。 我正在查看类似的问题和可悲​​的Immutable.js文档,我无法看到如何做到这一点:我尝试的语法没有像我期望的那样工作。

那么,你需要的是嵌套更新。 首先,您必须检查您已加载的帐户列表是否有此帐户。 其次,您必须更改activeAccount字段。 最后,将帐户添加(或更新)到loadedAccounts

这里需要注意的是你如何通过account财产。 如果你从某个地方派生它并作为Record传递,你可以通过=== (或.equals())进行比较,但它似乎只是一个简单的javascript对象 - 我会在以后想到它。

在代码方面,它将是这样的:

// we can do it by different ways, it is just one of them
const listWithLoadedAccounts = state.get('loadedAccounts');
const isAccountAlready = Boolean(
  listWithLoadedAccounts.filter(
    account => account.get('id') === action.account.id
  ).size
);

const patchedState = state.set('activeAccount', action.account.id);
return isAccountAlready
  ? patchedState.updateIn(['loadedAccounts'], list => list.map(account => account.get('id') === account.action.id ? new account(action.account) : account))
  : patchedState.updateIn(['loadedAccounts'], list => list.concat(new account(action.account)))

它不是理想的代码,可以进行重复数据删除,但是您可以理解 - 如果您需要更改嵌套字段或数据结构,请始终使用深度合并/更新。

您也可以直接设置新字段,例如:

const oldList = state.get('loadedAccounts');
const newList = oldList.concat(action.account);
const patchedState = state.set('loadedAccounts', newList);

但我个人发现它并不灵活且不一致,因为执行深度合并是非常常见的操作。

我希望这个例子有所帮助,我正在创建一个新的不可变列表,并首先执行更新,然后添加一个新元素。 我没有传递我想要替换的对象,但是你也可以传递你现有的对象,同样在更新方法中你可以访问当前项目

 class Test { a = null; b = null; constructor(a,b){ this.a=a; this.b=b; } } $("#test").html(""); function logme(item){ $("#test").append("<br/>"+JSON.stringify(item)); } function logmeNewLine(){ $("#test").append("<br/>"); } function listAddUpadte(key){ var index= list.get('data').findIndex(listing => { return listing.a === key; }); logme(' found index (-1 for not found) : ' + index); if(index >= 0){ logme("upadte"); list = list.set("data",list.get("data").update(index,function(item){ return new Test(key,"go"); })); }else { logme("add"); list = list.set("data",list.get("data").push(new Test(key,"go"))); } list.get('data').forEach(item=>{ logme(item); }); } var list = Immutable.fromJS({ "data":[new Test(6,"abhi"),new Test(4,"raj"),new Test(1,"ajay")] }); logme("intial data"); list.get('data').forEach(item=>{ logme(item); }); logmeNewLine(); logme("testing replace with a = 4 ") logmeNewLine(); listAddUpadte(4); logmeNewLine(); logme("testing add with a = 8 ") logmeNewLine(); listAddUpadte(8); logmeNewLine(); logmeNewLine(); logmeNewLine(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.7.2/immutable.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="test"></div> 

不是直接的答案,而是如何使用immutable.js添加到列表的示例:

let oldList = List([ 1, 2, 3, 4 ])
let newList = oldList.push(5)

暂无
暂无

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

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