首先來看看簡易專案管理網站的畫面上需要顯示那些資訊:
由於我們不希望資料散落在各個元件,因此傾向於使用 useReducer,將資料集中在一起管理,所以我們要將需要顯示的資料全部放在一個物件內。
根據以上的結構,可以轉換成:
{
title: '專案標題',
boards: [
{
id: 'board1',
name: '看板一',
cards: [
{
id: 'card1',
text: '卡片一'
},
{
id: 'card2',
text: '卡片二'
}
]
},
{
id: 'board2',
name: '看板二',
cards: [
{
id: 'card3',
text: '卡片三'
},
{
id: 'card4',
text: '卡片四'
}
]
}
]
}
上面的結構雖然看起來還算簡單,但巢狀結構的資料如果越多層,就代表之後要定義的更新邏輯就會更複雜,因此我們進一步嘗試將資料結構扁平化或正規化(normalize):
boards
底下、卡片就存在 cards
底下board1
底下['card1', 'card2']
就好['board1', 'board2']
來儲存綜合以上的規則來進行轉換,資料結構就會變成:
{
title: '專案標題',
boards: {
ids: ['board1', 'board2'],
byId: {
board1: {
name: '看板一',
cardIds: ['card1', 'card2']
},
board2: {
name: '看板二',
cardIds: ['card3', 'card4']
}
}
},
cards: {
byId: {
card1: '卡片一',
card2: '卡片二',
card3: '卡片三',
card4: '卡片四',
}
}
}
如此一來,之後要定義的更新邏輯就會變得比較簡單,以「更新 card3
的文字內容」為例:
在原本的資料結構中,我們要先知道 card3
是在 board2
中,然後再到 board2
的 cards
陣列中找到 card3
所在的位置,然後再更新該位置的 card3
物件。
正規化後的資料結構,我們只要直接更新 cards.byId.card3
物件就好,完全不用修改到 boards 底下的結構。
再來要定義資料更新的類型以及邏輯囉!
參考資料:
- Normalizing State Shape · Redux - https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape