2017-03-04 170 views
0

好吧,所以在編寫回應時遇到了問題,我發現它很常見。如果我有多個嵌套組件,在我的情況,我有:react,redux - 使用redux修改父組件

<AppView> 
    <Navigation/> // this is a navbar 
    <ViewHandler currentTab={props.currentTab}/> 
    <Footer/> 
</AppView> 

然後在<ViewHandler/>我有其他啞表象的成分,也有嵌套的組件。如果我在<ViewHandler>內的深度嵌套組件中有一個按鈕,並且我想通過更改我所在組件上方的許多父組件來響應該按鈕中的onClick,那麼我該怎麼做?在我的情況下,我會對該深度嵌套組件中單擊的按鈕作出反應,然後我想更改<Navigation>上的選定選項卡。我不想將一些回調函數作爲屬性傳遞下去,因爲它感覺非常透徹。

我學會了redux,因爲我讀過它解決了這個問題。但對我而言,它沒有。我使用react-redux的<Provider><AppView>訪問我的redux商店,我可以通過道具訪問商店(props.currentTab)。但是對於嵌套在<AppView>內的所有組件,他們無法訪問商店或我的任何動作創建者。如何在深度嵌套組件中修改我的商店,以便我可以在不傳遞大量回調函數的情況下更改父組件?或者這只是不正確的架構?我想REDX會解決這個問題,但事實並非如此。

是的,我連接了我的組件。我只是不喜歡將store.state信息作爲道具傳遞的想法,因爲它與許多嵌套組件非常冗餘。

+1

您沒有使用正確Redux的。 selectedTab應該來自store.state。它應該使用傳遞給它的屬性。點擊按鈕時,應更新商店狀態以反映所選標籤。這聽起來像你需要連接組件。只要用Provider包裝它,就不會像你想的那樣給予它訪問。 http://redux.js.org/docs/basics/UsageWithReact.html –

+0

請問您可以添加您爲商店,組件和操作編寫的代碼,以便我們提供幫助? – caisah

+0

@NormCrandall我正在使用connect(),以便我可以通過道具 – jrademacher

回答

0

Hoc(高階組件)是一種爲子組件提供方法和數據的包裝器,通常使用它是一個好主意,但它強制執行一些「規則」。

示例:如果您的HOC位於級別0,並且您具有深度嵌套的級別爲4的按鈕組件,該組件在此HOC中調用方法,您應該怎麼做?把它傳遞給所有4個級別?答案是沒有辦法!

因爲這樣做會將意大利麪條帶到它,每次你點擊這個按鈕,並假設綁定到它的方法將與國家(內部或商店本身)混亂,它會放棄所有4個級別,你可以通過使用shouldComponentUpdate()避免這種情況,但這樣做太多了,沒有用處。

因此,解決方案將連接每個組件與mapStateToPropsmapDispatchToProps,對不對?

好樣的,事實上在使用廣泛的反應和redux後,您會注意到,對於每個組件,在尺寸,兒童以及您應該放入的東西以及您應該放置的東西方面都有一個甜蜜點。

示例:在控制發送機制的表單中有一個按鈕,不需要爲該按鈕創建組件,它會增加複雜性而沒有任何好處。只需將它放在表單組件上,你就可以隨時使用了。

如果您確實需要調用動作或在深度嵌套組件和HOC之間傳遞道具,請在組件級別使用連接模塊(對於您的情況按鈕),但不會太多,因爲它會使組件更重(加載和顯示)。下面是一些提示,以幫助:

  • 你需要像specfic時儘量使用mapStateToProps,不回全倉,只需要一塊數據的,同爲mapDispatchToprops,只要綁定的方法你將不會使用其他任何東西。

  • 在你的情況下,按鈕不必知道哪個選項卡被選中,所以mapDispatchToProps就足夠了。

  • 避免深度嵌套組件處理某種邏輯,重構你的結構或創建該組件的HOC,在相反的邏輯更少的組件可以被嵌套很深

  • 如果你正在寫一個龐大的應用很多減速器和狀態,考慮使用選擇器,以及一些類似重新選擇的庫。

我知道,這是不是您想要的答案,但這一準則下會爲您節省重構的無數個小時。

希望它可以幫助

1

我不知道爲什麼你認爲你有送道具一路下來你的組件樹。這就是connectmapStateToProps可以幫助您避免的情況:它們允許您將應用程序狀態轉換爲僅用於需要它的組件的道具。

在按鈕的 onClick處理

,創建並分派終極版動作:

// button.js 

onClick={() => { 
    dispatch({ 
    payload: 1 // or whatever value 
    type: 'SET_SELECTED_TAB' 
    }); 
}} 

旁邊,有你的減速功能的手錶這一行動,並修改了一下終極版應用程序的狀態:

// reducer.js 

if (action.type === 'SET_SELECTED_TAB') { 
    return { 
    ...currentAppState, 
    selectedTab: action.payload 
    }; 
} 

最後,在您的<Navigation>組件的render功能中,您可以根據該應用程序狀態位的當前值決定顯示哪個選項卡:

// Navigation.js 

render() { 
    return (
    <div> 
     current tab: {this.props.selectedTab} 
    </div> 
); 
} 

訪問該狀態是通過connectmapStateToProps

// Navigation.js still 

const mapStateToProps = (appState) => { 
    return { 
    selectedTab: appState.selectedTab 
    }; 
}; 

export default connect(mapStateToProps)(Navigation); 
+0

訪問currentTab比你非常。這正是我所期待的。 – jrademacher

+0

我如何獲得調度()@Dan O – jrademacher