昨天介紹了如果是 object 型態的 state,在 React 會要怎麼更新。今天要來繼續延伸閱讀,來介紹 React 在他們官網推薦的 library Immer。
在面對巢狀的 object 的時候,如果要更新 state 我們會需要使用多個展開語法(spread syntax):
setPerson({
...person, // 先複製 person
artwork: { // 取代舊的 artwork
...person.artwork, // 複製 person.artwork
city: 'New Delhi' // 取代舊的 person.artwork 裡的 city
}
});
當層數越來越多的時候,更新邏輯的程式碼會越寫越長越複雜。這時候就可以來使用 Immer 去寫成像是有 side effect 的寫法(mutation):
updatePerson(draft => {
draft.artwork.city = 'Lagos';
});
但仍然保持 state 的 不可變性(immutable)。
想要在 React 裡面使用 Immer 的寫法,會有幾個步驟:
useState
改成 useImmer
- import { useState } from React
+ import { useImmer } from use-immer
剩下跟 useState
的用法一樣,先宣告 state
const [person, setPerson] = useImmer({
name: 'Niki de Saint Phalle',
artwork: {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
}
})
不一樣的是我們可以在使用 setPerson
的時候使用 draft
了,並且運用 draft
可以使用 mutation 的方式更新 state 但不會真的進行 mutate。
更多 Immer 在 React 裡的使用可以參考 Immer 的官方文件:
Immer 裡的 draft
,是用一個特別的 object
型態叫做 Proxy,它的功用就是會建立一個新的物件讓使用者對他進行操作,所以可以任意對他使用 side effect,最後 Immer 會查到在 draft
裡面有哪些值改變,再去生成一個全新更改後的 object。可以參考一下 Immer 官方附的介紹圖:
今天主要是在介紹 Immer 這個工具,現在我自己在工作的時候也都是用 useImmer
而不是 useState
,因為他在更新的時候就可以不用考慮自己寫的是不是 immutable 的了,大家也可以多試試看。明天的篇章會接著介紹 state 的陣列更新。
文章就到這邊,感謝大家耐心地看完,如果有任何問題與建議歡迎告訴我,明天見,晚安。