iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 21
0
Modern Web

使用 React 製作簡易專案管理網站:從基礎到實戰系列 第 21

[Day 21] React 攻城戰 - 資料儲存結構

  • 分享至 

  • xImage
  •  

資料儲存結構

首先來看看簡易專案管理網站的畫面上需要顯示那些資訊:

  • 標題
  • 看板
    • 名稱
    • 底下的卡片
      • 卡片的順序
      • 卡片內容

由於我們不希望資料散落在各個元件,因此傾向於使用 useReducer,將資料集中在一起管理,所以我們要將需要顯示的資料全部放在一個物件內。

根據以上的結構,可以轉換成:

{
  title: '專案標題',
  boards: [
    {
      id: 'board1',
      name: '看板一',
      cards: [
        {
          id: 'card1',
          text: '卡片一'
        },
        {
          id: 'card2',
          text: '卡片二'
        }
      ]
    },
    {
      id: 'board2',
      name: '看板二',
      cards: [
        {
          id: 'card3',
          text: '卡片三'
        },
        {
          id: 'card4',
          text: '卡片四'
        }
      ]
    }
  ]
}

上面的結構雖然看起來還算簡單,但巢狀結構的資料如果越多層,就代表之後要定義的更新邏輯就會更複雜,因此我們進一步嘗試將資料結構扁平化或正規化(normalize):

  • 每一種資料各自存在一個 key 底下。例如看板存在 boards 底下、卡片就存在 cards 底下
  • 每一筆資料用 id 當作 key。例如看板一就存在 board1 底下
  • 每一筆資料如果底下有其他種資料,只需要存 id 即可。例如看板一底下只要存 ['card1', 'card2'] 就好
  • 資料的順序另外用一個陣列來儲存資料的 id 即可。例如看版的順序另外用 ['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 中,然後再到 board2cards 陣列中找到 card3 所在的位置,然後再更新該位置的 card3 物件。

正規化後的資料結構,我們只要直接更新 cards.byId.card3 物件就好,完全不用修改到 boards 底下的結構。

下集預告

再來要定義資料更新的類型以及邏輯囉!

參考資料:

  1. Normalizing State Shape · Redux - https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

上一篇
[Day 20] React 攻城戰 - 簡易型專案管理網站簡介與架構
下一篇
[Day 22] React 攻城戰 - 資料更新邏輯 action
系列文
使用 React 製作簡易專案管理網站:從基礎到實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言