React Redux:更多容器与更少容器

Coo*_*ama 17 reactjs redux react-redux

随着我进一步实现redux +反应到一个相当复杂的应用程序,这取决于许多API请求加载单个页面,我无法决定是否最好在页面根部有一个容器组件来处理所有异步的东西,并将道具传递给哑组件,与多个容器组件相关,这些组件只关注他们需要的数据,以及获取他们需要的数据.我在这两种模式之间来回走动,发现它们各有利弊:

如果我在顶部放置一个容器组件:

  • 亲:所有isFetching道具和fetchSomeDependency()行动都可以在一个地方处理.
  • con:真正令人讨厌的缺点是我发现自己不得不通过多个组件转发道具和回调,而树中间的某些组件最终会与此绑定.

这是一个问题的视觉示例,显示了道具所需的关系:

<MyContainer
  data={this.props.data}
  isFetchingData={this.props.isFetchingData}
  fetchData={this.props.fetchData}
 >
   {!isFetchingData && 
     <MyModal
        someData={props.data}
        fetchData={props.fetchData}
      >
       <MyModalContent
         someData={props.data}
         fetchData={props.fetchData}
       >
          <SomethingThatDependsOnData someData={props.someData} />
          <SomeButtonThatFetchesData  onClick={props.fetchData} />
        </MyModalContent>
      </MyModal>
    }
 </MyContainer>
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,<MyModal /><MyModalContent />现在需要用什么都没有用它做道具关注,看到一个模式应该能够被重新使用,并且只用一个模式的文体素质有关.

起初上面看起来很棒,但是一旦我有100多个组件,它们都感觉非常纠结,我发现这些顶级容器组件的复杂性太高,我不喜欢,看到他们中的大多数(在应用程序中我"正在努力"取决于3个以上API请求的响应.

然后我决定尝试多个容器:

  • 亲:完全不需要转发道具.在某些情况下这样做仍然有意义,但它更灵活.
  • 亲:更容易重构的方式.我很惊讶我如何能够在没有任何破坏的情况下显着移动和重构组件,而在其他模式中,事情已经破坏了很多.
  • 亲:每个容器组件的复杂性要小得多.我的mapStateToProps并且mapDispatchToProps更加具体到它所在组件的目的.
  • con:任何依赖于异步内容的组件总是需要处理isFetching状态.这增加了在单个容器组件中处理它的模式中不必要的复杂性.

所以主要的困境是,如果我使用一个容器,我会在根容器和叶子组件之间的组件中获得这种不必要的复杂性.如果我使用多个容器,我会在叶子组件中获得更多的复杂性,并最终得到需要担心的按钮,isFetching 即使按钮不应该关注它.

我想知道是否有人找到了避免利弊的方法,如果有的话,你遵循的"经验法则"是什么来避免这种情况?

谢谢!

Coo*_*ama 1

自从我发布这个问题以来已经过去 2 年多了,这段时间我一直在使用 React/Redux。我现在的一般经验法则是:使用更多容器,但尝试以不需要了解isFetching.

例如,以下是我之前如何构建待办事项列表的典型示例:

  function Todos({ isFetching, items }) {
    if (isFetching) return <div>Loading...</div>

    return (
      <ul>
        {items.map(item => 
          <li key={item.id}>...</li>
        )}
      </ul>
    )
  }
Run Code Online (Sandbox Code Playgroud)

现在我会做更多类似的事情:

  function Todos({ items }) {
    if (!items.length) return <div>No items!</div>

    return (
      <ul>
        {items.map(item => 
          <li key={item.id}>...</li>
        )}
      </ul>
    )
  }
Run Code Online (Sandbox Code Playgroud)

这样,您只需连接数据,组件无需关心异步 API 调用的状态。

大多数事情都可以这样写。我很少需要isFetching,但当我这样做时通常是因为:

  1. 例如,我需要防止再次单击提交按钮,这会进行 API 调用,在这种情况下,可能应该调用 propdisableSubmit而不是isFetching,或者

  2. 我想在某些东西正在等待异步响应时显式显示加载程序。

现在,您可能会想,“您不想在上面的待办事项示例中获取项目时显示加载器吗?” 但实际上我不会。

这样做的原因是,在上面的示例中,假设您正在轮询新的待办事项,或者当您添加待办事项时,您“重新获取”待办事项。第一个示例中会发生的情况是,每次发生这种情况时,待办事项都会消失并频繁地替换为“正在加载...”。

然而,在不关心的第二个示例中isFetching,新项目只是简单地添加/删除。在我看来,这是更好的用户体验。

事实上,在发布本文之前,我浏览了我编写的交换接口的所有 UI 代码,该代码非常复杂,并且没有找到必须连接isFetching到我编写的容器组件的单个实例。