2016-03-04 57 views
2

我在構建React/Redux應用程序時遇到困難 - 我列出了我爲解決方案嘗試的選項所帶來的問題,但沒有什麼「感覺正確」,所以希望有人能夠幫助我出去了。爲反應/還原應用程序構建狀態

這裏是我的部件結構的粗略的想法:

<Dashboard> 
    <Widget1 dataFetcher=()=>{}> 
     <Header> 
      <Title> ... </Title> 
      <Menu> 
       <MenuItem {..cosmeticProps} text="OpenSettings" onClick=handleSettingsOpen> 
       <MenuItem {..cosmeticProps} text="Delete" onClick=handleWidgetDelete> 
      </Menu> 
     </Header> 
     <Body> 
      <Settings isOpen isValid fields onValidate onAutoComplete.. </Settings> 
      { ifError ? ErrorLayout} 
      { ifFetching ? FetchingLayout } 
      { ifValid ? DataLayout } 
     </Body> 
    </Widget1> 
    ... 
</Dashboard> 

而這裏的狀態結構(顯示爲完整的事件處理程序,不是因爲他們明確地州的一部分)

Dash: { 
    widgets: { 
     widget1: { 
      menu: { 
       isOpen: true, 

       handleSettingsOpen:()=>{} 
       handleWidgetDelete:()=>{} 
      } 
      settings: { 
       isOpen: true, 
       isValid: true, 
       fields: [...], 

       onValidate:()=>{}, 
       onAutoComplete:()=>{}, 
       onSave:()=>{} 
      } 
      data: { 
       isFetching: false, 
       isError: false, 
       items: [], 

       fetch:()=>{} 
       parse:()=>{} 
      } 
     } 
     ... 
    } 
} 

選項1:

連接儀表板並根據需要傳遞給子代。即,

連接 - dashboard.js

stateToProps()=> { widgets: state.widgets } 
dispatchToProps()=> { handleSettingsOpen, handleWidgetDelete handleSettingsSave ... } //Dashboard would bind these with moduleid while rendering 
  • 臨:其他一切可以「啞巴」,單一數據源
  • 缺點:知道得太多關於狀態,道具/分派清單它只需向下傳遞,使醜陋的閱讀

選項2:

構建「連接」小部件並在儀表板中使用它。

連接,widget.js

stateToProps()=> { state.widgets[props.widgetid] } 
dispatchToProps()=> { handleSettingsOpen, handleWidgetDelete handleSettingsSave ... } 
  • 臨:儀表盤現在可以是一個愚蠢的容器,它是無論如何
  • 缺點:小部件知道太多關於國家結構?

選項3: 生成連接各個組件的版本和組裝後

連接-menu.js

stateToProps()=> { state.widgets[props.widgetid].menu } 
dispatchToProps()=> { handleSettingsOpen, handleWidgetDelete } 
連接-settings.js

stateToProps()=> { state.widgets[props.widgetid].settings } 
dispatchToProps()=> { handleSave, handleValidate } 
  • 專業版:每個組件都準確地處理它所關注的狀態片
  • Con:組件監聽狀態的組件太多?還有誰是「組裝」的問題。

選項3。1: 重組狀態爲:

Dashboard: { 
    widgets: { ..} 
    menu: {widgetid: {isopen ..}} 
    settings: {widgetid: {widgetid ..}} 
} 

(州是平坦的這種做法,但不知道這是否重要得多)

總體而言,這可能是幼稚/顯而易見的,但對我來說與貿易關閉似乎有一個家長,要麼知道太多的國家,要麼太多關於兒童如何放在一起。你會如何處理這個問題?

+0

re:option3,組件不聽狀態,商店可以自己更新_push_,你不用擔心訂閱過多 – dandavis

+0

我同意選項3是最好的。也總是儘量讓你的數據結構儘可能平坦。這太嵌套了'Dash:{widgets:{widget1:{menu:{'。 –

+0

謝謝你的答覆 - 你能解釋一下_why_嵌套結構是不好的嗎?與嵌套,如果以後我需要刪除一個小部件,我可以從小部件結構中刪除它;如果它是平的,我需要從其他所有頂級項目中清理它;這將提供什麼好處? – Naren

回答

0

選項3:菜單和設置知道「widgetId」有意義嗎?看起來如果他們只是分別接收屬性菜單或設置,他們會更加可重用。

選項1:是否要爲每個支持的窗口小部件組件更新控制面板stateToProps和dispatchToProps?

由於這些原因,我喜歡選項2,連接的Widget1。

至於狀態嵌套深度,Redux Async Actions有一個「關於嵌套實體的註釋」,暗示避免深度嵌套實體以避免重複數據。

在您的示例中,如果任何小部件具有重複的菜單或設置狀態對象,則標準化狀態將允許小部件共享相同的狀態。

Dashboard: { 
    widgets: { 
     widget1: {menuId:1, settingsId: 1, ...}, 
     widget2: {menuId:1, settingsId: 1, ...}, 
    }, 
    menus: {1: {...}}, 
    settings: {1: {...}} 
} 

實際上,在這個結構中,Menu和Settings只需要知道menuId或settingsId,而不是widgetId。儘管如此,我仍然更喜歡連接小部件