2017-06-06 33 views
1

我有一個API響應,它有很多嵌套的實體。我使用normalizr來保持redux狀態儘可能平坦。
例如。 API響應看起來象下面這樣:
Redux + Normalizr:在Redux狀態下添加和刪除規範化的實體

{ 
    "id": 1, 
    "docs": [ 
    { 
     "id": 1, 
     "name": "IMG_0289.JPG" 
    }, 
    { 
     "id": 2, 
     "name": "IMG_0223.JPG" 
    } 
    ], 
    "tags": [ 
    { 
     "id": "1", 
     "name": "tag1" 
    }, 
    { 
     "id": "2", 
     "name": "tag2" 
    } 
    ] 
} 

這種反應使用normalizr使用下面給出的方案進行歸一化:

const OpeningSchema = new schema.Entity('openings', { 
    tags: [new schema.Entity('tags')], 
    docs: [new schema.Entity('docs')] 
}); 

和下面是它的外觀則:

{ 
    result: "1", 
    entities: { 
    "openings": { 
     "1": { 
      "id": 1, 
      "docs": [1,2], 
      "tags": [1,2] 
     } 
    }, 
    "docs": { 
     "1": { 
     id: "1", 
     "name": "IMG_0289.JPG" 
     }, 
     "2": { 
     id: "2", 
     "name": "IMG_0223.JPG" 
     } 
    }, 
    "tags": { 
     "1": { 
      "id": 1, 
      "name": "tag1" 
     }, 
     "2": { 
      "id": 2, 
      "name": "tag2" 
     } 
    } 
    } 
} 

現在還原狀態如下所示:

state = { 
    "opening" : { 
     id: 1, 
     tags: [1,2], 
     docs: [1,2] 
    }, 
    "tags": [ 
     { 
      "id":1, 
      "name": "tag1" 
     }, 
     { 
      "id":2, 
      "name": "tag2" 
     } 
    ], 
    "docs": [ 
     { 
      "id":1, 
      "name": "IMG_0289.JPG" 
     }, 
     { 
      "id":2, 
      "name": "IMG_0223.JPG" 
     } 
    ] 
} 

現在,如果我派遣一個動作添加tag,然後添加一個tag對象state.tags但它不會更新state.opening.tags陣列。同樣的行爲,同時刪除標籤。

我保留opening,tagsdocs在三個不同的reducer。

這是一種不一致的狀態。我能想到的通過以下方式來保持狀態保持一致:

  1. 我派遣一個動作來更新標籤和聽它在這兩個tags減速機和減速opening和更新,在這兩個地方隨後標籤。
  2. 使用標籤更新打開的修補程序請求會返回開放響應。我可以再次發送標準化響應和設置標籤的動作,打開等適當的一致性。

什麼是正確的方法來做到這一點。實體不應該觀察相關實體的變化並自行進行變更。或者有任何其他模式可以採取任何此類行動。

回答

2

首先總結normalizr的工作原理:normalizr將嵌套的API響應展平到您的模式定義的實體上。因此,當您製作最初的GET openings API請求時,normalizr將響應展平,並創建Redux entities和扁平對象:openings,docs,tags

你的建議是可行的,但我發現normalizr真正的好處在分離API數據從UI狀態;所以我不會自己更新Redux商店中的數據...我所有的API數據都保存在entities中,它們不會被我更改;他們是香草後端數據...我所做的只是在狀態更改API操作時執行GET,並規範GET響應。對於稍後我會擴展的DELETE案例有個小例外......中間件將處理這種情況,因此如果您沒有使用過,則應該使用一個。我創建了我自己的中間件,但我知道redux-promise-middleware非常受歡迎。

在上面的數據集中;當你添加一個新的tag時,我假設你正在製作一個API POST來這樣做,然後更新後端。然後,你應該做的另一個GET openings將更新爲entities開口及其所有嵌套模式。

當你刪除一個tag,例如標籤[2],在發送DELETE請求到後端時,您應該取消您實體狀態中已刪除的對象,即。 entities.tags[2] = null再次使GET openings更新您的normalizr實體。