[英]How to update element inside List with ImmutableJS?
這是官方文檔所說的
updateIn(keyPath: Array<any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Array<any>, notSetValue: any, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, notSetValue: any, updater: (value: any) => any): List<T>
普通的Web開發人員(非功能程序員)無法理解這一點!
我非常簡單(對於非功能性方法)的情況。
var arr = [];
arr.push({id: 1, name: "first", count: 2});
arr.push({id: 2, name: "second", count: 1});
arr.push({id: 3, name: "third", count: 2});
arr.push({id: 4, name: "fourth", count: 1});
var list = Immutable.List.of(arr);
如何更新list
,其中名稱為third的元素的計數設置為4 ?
最合適的情況是使用findIndex
和update
方法。
list = list.update(
list.findIndex(function(item) {
return item.get("name") === "third";
}), function(item) {
return item.set("count", 4);
}
);
PS並不總是可以使用地圖。 例如,如果名稱不唯一,我想更新具有相同名稱的所有項目。
使用.setIn()可以執行相同的操作:
let obj = fromJS({
elem: [
{id: 1, name: "first", count: 2},
{id: 2, name: "second", count: 1},
{id: 3, name: "third", count: 2},
{id: 4, name: "fourth", count: 1}
]
});
obj = obj.setIn(['elem', 3, 'count'], 4);
如果我們不知道要更新的條目的索引。 使用.findIndex()很容易找到它:
const indexOfListToUpdate = obj.get('elem').findIndex(listItem => {
return listItem.get('name') === 'third';
});
obj = obj.setIn(['elem', indexOfListingToUpdate, 'count'], 4);
希望能幫助到你!
這是官方文檔說的......
updateIn
您不需要updateIn
,僅適用於嵌套結構。 您正在尋找update
方法 ,它具有更簡單的簽名和文檔:
返回一個新的List,其索引處的更新值為使用現有值調用updater的返回值,如果未設置index,則返回notSetValue。
update(index: number, updater: (value: T) => T): List<T> update(index: number, notSetValue: T, updater: (value: T) => T): List<T>
正如Map::update
文檔所暗示的那樣,它“ 等同於: list.set(index, updater(list.get(index, notSetValue)))
”。
其中名稱為“third”的元素
這不是列表的工作方式。 您必須知道要更新的元素的索引,或者您必須搜索它。
如何更新列表,其中名稱為third的元素的計數設置為4?
這應該這樣做:
list = list.update(2, function(v) {
return {id: v.id, name: v.name, count: 4};
});
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
說明
更新Immutable.js集合始終返回這些集合的新版本,而原始集合保持不變。 因此,我們不能使用JavaScript的list[2].count = 4
變異語法。 相反,我們需要調用方法,就像我們可能使用Java集合類一樣。
讓我們從一個更簡單的例子開始:只是列表中的計數。
var arr = [];
arr.push(2);
arr.push(1);
arr.push(2);
arr.push(1);
var counts = Immutable.List.of(arr);
現在,如果我們想要更新第3項,那么普通的JS數組可能看起來像: counts[2] = 4
。 由於我們不能使用變異,並且需要調用方法,而是我們可以使用: counts.set(2, 4)
- 這意味着在索引2
處設置值4
。
深度更新
您給出的示例包含嵌套數據。 我們不能只在初始集合上使用set()
。
Immutable.js集合有一系列方法,名稱以“In”結尾,允許您在嵌套集中進行更深層次的更改。 最常見的更新方法具有相關的“In”方法。 例如,對於set
有setIn
。 這些“In”方法不接受索引或鍵作為第一個參數,而是接受“關鍵路徑”。 關鍵路徑是索引或鍵的數組,用於說明如何獲取要更新的值。
在您的示例中,您希望更新索引2中列表中的項目,然后更新該項目中鍵“count”的值。 所以關鍵路徑是[2, "count"]
。 setIn
方法的第二個參數就像set
一樣工作,它是我們想要放在那里的新值,所以:
list = list.setIn([2, "count"], 4)
找到正確的關鍵路徑
更進一步,你實際上說你想要更新名稱為“3”的項目,這與第3項不同。 例如,您的列表可能沒有排序,或者可能之前刪除了名為“two”的項目? 這意味着首先我們需要確保我們確實知道正確的關鍵路徑! 為此我們可以使用findIndex()
方法(順便說一句,它的工作方式幾乎與Array#findIndex一樣 )。
一旦我們在列表中找到了包含我們想要更新的項目的索引,我們就可以提供我們希望更新的值的關鍵路徑:
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
注意: Set
與Update
原始問題提到了更新方法而不是set方法。 我將解釋該函數中的第二個參數(稱為updater
),因為它與set()
不同。 而第二個參數set()
是我們希望新的價值,第二個參數來update()
是接受於前值和返回,我們希望新的值的函數 。 然后, updateIn()
是update()
的“In”變體,它接受一個鍵路徑。
比方說,我們想要一個不僅將計數設置為4
示例變體,而是增加現有計數,我們可以提供一個函數,將現有值加1:
var index = list.findIndex(item => item.name === "three")
list = list.updateIn([index, "count"], value => value + 1)
使用.map()
list = list.map(item =>
item.get("name") === "third" ? item.set("count", 4) : item
);
var arr = []; arr.push({id: 1, name: "first", count: 2}); arr.push({id: 2, name: "second", count: 1}); arr.push({id: 3, name: "third", count: 2}); arr.push({id: 4, name: "fourth", count: 1}); var list = Immutable.fromJS(arr); var newList = list.map(function(item) { if(item.get("name") === "third") { return item.set("count", 4); } else { return item; } }); console.log('newList', newList.toJS()); // More succinctly, using ES2015: var newList2 = list.map(item => item.get("name") === "third" ? item.set("count", 4) : item ); console.log('newList2', newList2.toJS());
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
我非常喜歡thomastuts網站上的這種方法:
const book = fromJS({
title: 'Harry Potter & The Goblet of Fire',
isbn: '0439139600',
series: 'Harry Potter',
author: {
firstName: 'J.K.',
lastName: 'Rowling'
},
genres: [
'Crime',
'Fiction',
'Adventure',
],
storeListings: [
{storeId: 'amazon', price: 7.95},
{storeId: 'barnesnoble', price: 7.95},
{storeId: 'biblio', price: 4.99},
{storeId: 'bookdepository', price: 11.88},
]
});
const indexOfListingToUpdate = book.get('storeListings').findIndex(listing => {
return listing.get('storeId') === 'amazon';
});
const updatedBookState = book.setIn(['storeListings', indexOfListingToUpdate, 'price'], 6.80);
return state.set('book', updatedBookState);
你可以使用map
:
list = list.map((item) => {
return item.get("name") === "third" ? item.set("count", 4) : item;
});
但這將遍及整個集合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.