iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0

前兩天介紹了如何更新 state 內的 object,今天則是要來介紹如何更新陣列(Array)。
今天的文章參考官方文件的:

因為是更新 state,所以我們也會需要在更新陣列的時候是 immutable 的,但是一些 JavaScript 內建的 Array 方法都會是有 side effect 的(更改原陣列)像是 pushpop 的陣列新增跟刪除,或是排列的 sort 之類的,官方文件有幫忙整理一個表格可以直接看:

https://ithelp.ithome.com.tw/upload/images/20251005/2016302485YUYSh3qG.png

我們在更新 state 的時候,盡量要少用這些具有 side effect 的方法,除非我們是使用 Immer
也比較要注意的是 spliceslice 雖然功能差不多,但 splice 是會 mutate 的,而 slice 不會,可能需要特別注意一下。

新增資料進陣列

如果不能使用 push,要新增一個新項目,會跟 object 一樣,可以使用展開語法,不過 object 的如果使用一樣的 key 會取代舊的,陣列的則是會直接新增一個。

setArtists(
  [
    ...artists, // 複製舊的陣列
    { id: nextId++, name: name } // 新增一個新的項目在陣列最後方
  ]
);

如果想把最新的放在第一個,就把展開語法放在後面就可以了。

刪除資料

另一個常見的更新會是刪除陣列裡的資料,這時候就可以使用 filter 這個方法,透過條件式留下符合條件的資料。因為 filter 是 immutable 的 function 所以可以放心使用他。

// 刪除 artists 裡 id 跟 artist.id 一樣的
setArtists(
  artists.filter(a => a.id !== artist.id)
);

使用 map 重整陣列

有時候我們會想把陣列的資料重新整理出一個新陣列,這時候就會用到方法 map。這也是一個非常容易使用到的方法,我自己比較常用的時候是要把資料整理成顯示 UI 好用的格式的時候,就可以使用到。或是想幫陣列內的資料多加個標注,譬如說有一個陣列有學生考試成績,然後我們可以使用 map,把一定區間的分數歸類成 A-F 的級別之類的。

map 還可以有另一種使用,就是可以獲得每個 item 的 index,並且透過條件式去更新陣列內容,這樣就可以得到類似 arr[0] = '新資料' 的取代效果(用 map 會把陣列裡的每個一個 item 都跑過一次所以可能效能會不太一樣)。

從指定的位置插入新資料

前面介紹使用展開語法進行陣列的資料新增,但那樣的寫法只能新增最前跟最後,如果是想在任意的陣列位置更新的話,就會需要先使用 slice 獲得前後的兩個子陣列,最後再用展開語法把前後兩個陣列展開,中間再放我們想要新增的資料:

const nextArtists = [
      // 新增位置前的子陣列:
      ...artists.slice(0, insertAt),
      // 新增的資料:
      { id: nextId++, name: name },
      // 新增位置後的子陣列:
      ...artists.slice(insertAt)
    ];
    setArtists(nextArtists);

使用展開語法複製陣列後更新

如果真的想使用像是 reverse()sort() 等具有 side effect 的方法,可以先使用展開語法複製一份陣列後再更新:

const nextList = [...list];
nextList.reverse();
setList(nextList);

這樣舊的資料就不會被動到,但是要注意,複製一份陣列的用法,不能去 mutate 陣列裡的 object

const nextList = [...list];
nextList[0].seen = true; // 也會更新到舊的 list[0].seen
setList(nextList);

原因是 nextList[0]list[0] 會指到同一個 object 所以更新 nextList 的 object 就會更新到 list 的 object。真的要更新就要使用 map 再用 object 的展開語法更新 object

小結

今天介紹了各種沒有 side effect 更新陣列的方法,如果真的還是想使用那些 side effect function 的話,也可以直接都使用 Immer 就好,這樣就還是能確保 state 的 immutable。
今天的文章就介紹到這邊,感謝大家耐心地看完,如果有任何建議與問題,都歡迎跟我說,明天見,晚安。


上一篇
Day 20 - 更新 State 內的 Object Part 2
下一篇
Day 22 - 使用 Input Form 介紹 React State 概念
系列文
重溫 React 官方文件回到最初的起點23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言