【譯】像數據庫同樣設計你的 redux 數據

翻譯:瘋狂的技術宅
做者:Nick Sweeting
英文標題:Shape your redux store like your database
英文原文:https://hackernoon.com/shape-...
說明:本專欄文章首發於公衆號:jingchengyideng 。javascript

clipboard.png

使用索引能夠從多個維度表現數據。(此處應爲動圖,請看原文)html

最近我在RC聊天系統瀏覽關於 JavaScript 的一些討論時,注意到了Kate Ray的一個問題:前端

應該怎樣在 redux 存儲中結構話個人數據?java

的確,這是使用 redux 時最多見的問題之一。react

有不少須要考慮的東西,你常常會像訪問一個行列表同樣遍歷數據嗎? 你須要以O(1)的時間複雜度快速訪問某些條目嗎?git

我在實踐中獲得了一些經驗,一般在訪問時間和迭代的難易程度之間作一些權衡。github

一些常見的方法

若是你須要存儲一些每一個項目都帶有id的數據,可使用Array, Object, 或者 對象數組來保存。數據庫

數組對象[{values}]

這是最多見的一種範式。它使迭代變得容易,可是不通過迭代和過濾就不能快速訪問特定條目。redux

categories: [
  {name: 'abs',  id: '32o8wafe', exercises: ['crunches', 'plank']},
  {name: 'arms', id: 'oaiwefjo', exercises: [...]},
  {name: 'legs', id: 'aoijwfeo', exercises: [...]},
]

id爲索引的對象{id: {values}}

這種方法能夠是你以O(1)的時間複雜度快速訪問每一個項目,可是在使用object.values()進行迭代時,不能很容易地訪問給定項目對應的id後端

對象數組 [{id: {values}}]

這讓你能夠遍歷列表並輕鬆訪問id和值,可是它作到以O(1)的時間複雜度快速訪問,由於它是一個數組。

categories: [
  {32o8wafe: {name: 'abs',  exercises: [...]},
  {oaiwefjo: {name: 'arms', exercises: [...]},
  {3oij2e3c: {name: 'legs', exercises: [...]},
]

把它像數據庫同樣構形成由id對行進行索引的結構

在學習redux的過程當中,我在Monadical偶然發現了一種不一樣的方法,它使咱們受益於簡單的Object.values(state.categories),並可以以O(1)的時間複雜度快速對單個項目的訪問:

categories: {
  32o8wafe: {id: '32o8wafe', name: 'abs',  exercises: [...]},
  oaiwefjo: {id: 'oaiwefjo', name: 'arms', exercises: [...] },
  3oij2e3c: {id: '3oij2e3c', name: 'legs', exercises: [...] },
}

請注意id既是行的鍵,同時也是行自己的屬性。這一點點重複使咱們在訪問時間上有了很大的靈活性。這也與Redux文檔推薦的歸一化(也稱扁平)模型兼容。

如今你能夠遍歷數據了,也能夠在迭代時訪問id

Object.values(categories).map(cat => ({id: cat.id, name: cat.name}))

或者經過id快度訪問任何項目!

categories[category_id].name

咱們將這樣組織好的數據發送到前端,前端就不須要作任何處理來生成id: values映射,從而也就減小了錯誤的產生。在後端很容易作到這一點,由於你極可能從數據庫中提取數據,而數據庫中已經存在id字段,能夠直接將其做爲鍵使用。

索引的力量

請注意,咱們上面介紹的結構只是一些行的索引,索引是id。你也能夠這樣設計本身的存儲結構:使用你想要用的字段生成索引,來達到O(1)的時間複雜度進行快速訪問

按名稱索引類別:

categories_by_name = {
  abs: '32o8wafe',
  arms: 'oaiwefjo',
  legs: '3oij2e3c',
}
const get_category_by_name = (store, name) =>
    store.getState().categories[categories_by_name[name]]

也能夠爲一樣的數據構建儘量多的索引,這樣將使你在任何列上基於O(1)的速度進行訪問,就像在數據庫中同樣。

clipboard.png

把你存儲的數據想象成爲圖書館,能夠用索引快速找到任何項目(此處應爲動圖,請看原文)

Normalizr與Reselect

這裏描述的模式正是Normalizr庫所使用的模式。若是你想把你的數據扁平化(按類型分開),就像我前面介紹的索引概念同樣,請閱讀Normalizr的文檔《Redux Without Profanity docs》。

Redux 和 Normalizr 與 Reselect 配合的也很好,若是你關心性能,而且喜歡有一箇中央列表的記憶選擇器,能夠關注一下。

擴展閱讀

歡迎掃描二維碼關注公衆號,天天推送我翻譯的技術文章。

clipboard.png

相關文章
相關標籤/搜索