2017-03-04 121 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