2017-07-28 109 views
4

TL; DR:如果一個可複用組件具有一些複雜的邏輯來管理自己的狀態(想一想:帶有自動補全,表情符號等的Facebook註釋文本框)如何使用存儲,動作和縮減器來管理狀態這個組件的多個實例遍佈整個網站?如何組織可重用組件的Redux狀態?

考慮官方的redux回購中的real-world example。 在這裏面,我們有:

  • 一個RepoPage,它顯示誰已經出演一個特別的回購協議的用戶列表,
  • 一個UserPage,顯示這是由特定用戶
  • 一個List出演回購名單,這是足夠通用的,它可以顯示用戶列表或回購,提供items和方式renderItem。特別是RepoPage使用User組件來顯示爲回購單元加星標的每個用戶,並且UserPage使用Repo單元來顯示每個加星標的回購單元。

假設我真的想要所有的狀態在Redux中。

特別是,我希望每個RepoPage和UserPage上的每個List的狀態由Redux管理。這已經在本例中的照顧,由一個聰明的三級深樹:

  • 在頂層的關鍵說什麼樣的分量數據是(在本例中它被稱爲store.pagination
  • 則存在對於每個特定類型的上下文,其中,組件可以是(store.pagination.starredByUserstore.pagination. stargazersByRepo
  • 然後作爲有獨特的上下文有儘可能多的密鑰的分支(store.pagination.starredByUser[login]store.pagination. stargazersByRepo[repo]

我FE el這三個級別也對應於:組件類型,父類型,父級id。

但是,我不知道如何擴展這個想法,以處理List組件本身有很多孩子的情況,在Redux中有一個值得追蹤的狀態。

我特別想知道如何在其中實現一個解決方案:

  • User組件保持不變
  • Repo組件有一個按鈕,用於切換其背景顏色
  • 每個Repo的狀態組件由Redux管理

(我很樂意使用一些擴展到終極版,仍然採用減速,但不想去「只是不停地在當地做出反應狀態」,對於這個問題的目的)

我的研究至今

  • 它看起來像在Elm中Actions(消息)是可以以這種方式嵌套的代數數據類型,父組件可以解開消息的「外部信封」並將用於孩子的內部動作傳遞給子Reducer (更新)。
  • 由於在Redux中使用字符串作爲動作類型的慣例,上述想法的自然翻譯是使用前綴,而這似乎是prism(以前稱爲redux-elm)所做的: action.type由通過組件樹指示路徑的子字符串組成。 OTOH在this comment棱鏡筆者tomkis解釋說,榆樹架構是終極版缺少的最重要的部分是行動的組成
  • 上述兩種方法似乎是擴大在Reusing Reducer Logic
  • 描述方法的版本我沒有充分把握redux-fly如何在內部工作,但它似乎使用有效負載而不是action.type通過其在store中的安裝路徑來標識組件實例,由於組件樹由組件樹手動構造的方式也對應組件樹中的路徑
  • WinAPI,在我看來,與Redux相似,如果你斜視,使用唯一的hWnd標識對於每一個控制,這使得它非常容易檢查action是否適用於您,並決定您的州在store的哪個位置。
  • 上述想法很可能會導致Documentation suggestion/discussion: Reusing Reducer Logic中描述的內容,其中每種類型的組件都有自己的扁平子樹,並由唯一的id索引。
  • 上面鏈接的鏈接描述的另一個想法是爲特定類型的組件編寫一個reducer,然後讓父組件的reducer調用它(這也意味着,父類負責決定在哪裏店子的狀態所在地 - 再次,這似乎類似於榆樹架構給我)
  • 一個很有趣的討論More on reusability for custom components其中一個建議的細節改變一個類似於上面給出特別上述討論
  • 包含用戶nav的a proposition,以這種方式遞歸地組織存儲樹,即組件的狀態是兩種分支中的子樹:一種用於私人東西,另一種用於子組件的「表格」,w這裏每個子組件類都有它自己的「表」,並且每個子實例都有一個唯一鍵,該表中的狀態是遞歸存儲的。訪問這些孩子的唯一密鑰存儲在「私人」部分。這與我想象的WinAPI非常相似:)
  • 另一個elm-inspired proposition來自同一個線程的用戶sompylasar將使用包含兒童動作的動作作爲「matrioshka」風格中的有效載荷,在我看來,它模仿代數類型構造函數嵌套在Elm中
  • redux-subspace被推薦用於棱鏡的discussion about Global Actions,作爲一種既受Elm啓發又允許您採取全局行動的庫。
+1

這裏是redux-subspace的創建者。最近,我對「真實世界」示例進行了一次嘗試,以及它如何使用孤立的組件進行查看。看看[回購](https://github.com/ioof-holdings/redux-subspace/tree/master/examples/real-world)或[沙箱](https://codesandbox.io/s/github/ioof-holdings/redux-subspace/tree/master/examples/real-world)如果你有興趣。 –

回答

1

我將試圖解釋這是由榆樹郎靈感,已經被移植到打字稿理念之一:

比方說,我們有以下的狀態非常簡單的組件

interface ComponentState { 
    text: string 
} 

組件可以通過以下2個動作來減少。

interface SetAction { 
    type: 'SET_VALUE', payload: string 
} 

interface ResetAction { 
    type: 'RESET_VALUE' 
} 

型工會對於那些2個行動(請看打字稿的識別聯合):

type ComponentAction = SetAction | ResetAction; 

減速這個應該有THW以下簽名:

function componentReducer(state: ComponentState, action: ComponentAction): ComponentState { 
    // code 
} 

我們「嵌入「在我們需要將數據模型封裝在父組件中的這個較大組件中的這個簡單組件:

interface ParentComponentState { 
    instance1: ComponentState, 
    instance2: ComponentState, 
} 

因爲redux中的動作類型需要全局唯一,所以我們無法爲組件實例分派單個動作,因爲它將由兩個實例處理。其中一個想法是包裝單個部分的動作爲母公司行動以下技術:

interface Instance1ParentAction { 
    type: 'INSTNACE_1_PARENT', 
    payload: ComponentAction, 
} 

interface Instance2ParentAction { 
    type: 'INSTNACE_2_PARENT', 
    payload: ComponentAction, 
} 

家長行動聯盟將具有以下特徵:

type ParentComponentAction = Instance1ParentAction | Instance2ParentAction; 

而且這項技術的最重要的事情 - 父縮減器:

function parentComponentReducer(state: ParentComponentState, action: ParentComponentAction): ParentComponentState { 
    switch (action.type) { 
     case 'INSTNACE_1_PARENT': 
      return { 
       ...state, 
       // using component reducer 
       instance1: componentReducer(state.instance1, action.payload), 
      }; 
     // 
    } 
} 

使用判別聯盟另外給父母和孩子減速器的類型安全。

相關問題