【问题标题】:react, redux - Modifying parent components with reduxreact, redux - 使用 redux 修改父组件
【发布时间】:2017-07-24 16:36:27
【问题描述】:

好的,所以我在 react 编程时遇到了问题,我发现这是一个常见的问题。如果我有多个嵌套组件,就我而言,我有:

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

然后在&lt;ViewHandler/&gt; 我有其他愚蠢的表示组件,它们也有嵌套组件。如果我在&lt;ViewHandler&gt; 内的深层嵌套组件中有一个按钮,并且我想通过更改我所在组件上方的许多父组件来响应该按钮的 onClick,我该怎么做?在我的情况下,我会对在该深层嵌套组件中单击的按钮做出反应,然后我想更改&lt;Navigation&gt; 上的选定选项卡。我不想将一堆回调函数作为属性传递下去,因为那感觉非常棒。

我学习了 redux,因为我读到它解决了这个问题。但对我来说没有。我正在使用 react-redux 的 &lt;Provider&gt; 授予 &lt;AppView&gt; 访问我的 redux 商店的权限,并且我可以通过道具 (props.currentTab) 访问商店。但是对于嵌套在&lt;AppView&gt; 中的所有组件,它们无权访问商店或我的任何动作创建者。如何从深度嵌套的组件中修改我的商店,以便我可以更改父组件而无需向下传递大量回调函数?或者这只是不正确的架构?我以为 redux 会解决这个问题,但它没有。

是的,我已经连接了我的组件。我只是不喜欢将 store.state 信息作为 props 传递的想法,因为它对于许多嵌套组件来说非常多余。

【问题讨论】:

  • 您没有正确使用 redux。 selectedTab 应该来自 store.state。它应该使用传递给它的属性。单击按钮时,应更新商店状态以反映所选选项卡。听起来您还需要连接组件。只是用 Provider 包装它,并没有像你想的那样给它访问权限。 redux.js.org/docs/basics/UsageWithReact.html
  • 能否请您添加我们为您的商店、组件和操作编写的代码,以便我们提供帮助?
  • @NormCrandall 我正在使用 connect() 以便我可以通过 props 访问 currentTab

标签: javascript reactjs redux


【解决方案1】:

我不知道你为什么认为你必须将 props 一路向下发送到组件树。这就是 connectmapStateToProps 可以帮助您避免的事情:它们让您将应用程序状态的位转换为仅用于需要它的组件的道具。

在按钮的 onClick 处理程序中,创建并调度 Redux 操作:

// button.js

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

接下来,让你的 reducer 函数监视这个动作并修改一些 Redux 应用状态:

// reducer.js

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

最后,在&lt;Navigation&gt; 组件的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);

【讨论】:

  • 非常感谢。这正是我想要的。
  • 我如何访问 dispatch() @Dan O
【解决方案2】:

Hoc(高阶组件)是为子组件提供方法和数据的包装器,通常使用它是个好主意,但它强制执行一些“纪律”。

示例:如果您的 HOC 位于级别 0,并且您在级别 4 有一个深度嵌套的按钮组件,它调用同一 HOC 中的方法,您应该怎么做?将其传递到所有 4 个级别?答案是不可能!

因为这样做会带来意大利面条,所以每次单击此按钮时,假设绑定到它的方法会与状态(内部或商店本身)混淆,它将重新渲染所有 4 个级别,您可以避免通过使用shouldComponentUpdate() 可以做到这一点,但这是太多的工作,没有任何用处。

所以解决方案是将每个组件与 mapStateToPropsmapDispatchToProps 连接,对吧?

好吧,实际上在广泛使用 react 和 redux 之后,您会注意到对于每个组件,在大小、子级以及应该放入什么和不应该放入什么方面都有一个最佳点。

示例:您在控制发送机制的表单中有一个按钮,无需为按钮制作组件,它会增加复杂性而没有任何好处。只需将它放在表单组件上,您就可以使用它们了。

如果您确实需要调用操作或在深度嵌套的组件和 HOC 之间传递道具,请在组件级别使用连接模块(对于您的情况是按钮),但不要太多,因为它会使您的组件更重(加载和显示)。这里有一些帮助提示:

  • 使用 mapStateToProps 时需要尽可能具体,不要返回整个商店,只返回所需的数据,对于 mapDispatchToprops 也是如此,只需绑定您将不使用其他任何内容的方法。

  • 在您的情况下,按钮不必知道选择了哪个选项卡,因此 mapDispatchToProps 就足够了。

  • 避免处理某种逻辑的深层嵌套组件,重构您的结构或为该组件创建一个 HOC,相反逻辑较少的组件可以深层嵌套

  • 如果您正在编写一个包含大量 reducer 和状态的大型应用程序,请考虑使用选择器和一些库,例如 reselect。

我知道这不是您所期望的答案,但遵循此指南将为您节省无数小时的重构时间。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2018-12-03
    • 1970-01-01
    • 2019-09-05
    • 2018-05-19
    • 1970-01-01
    • 2017-09-16
    相关资源
    最近更新 更多