首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >React :更多的容器和更少的容器

React :更多的容器和更少的容器
EN

Stack Overflow用户
提问于 2016-09-07 19:30:25
回答 5查看 4.7K关注 0票数 19

随着我对redux +的实现深入到一个相当复杂的应用程序中,这个应用程序依赖于多个API请求来加载单个页面,我很难决定是否最好在页面的根部有一个容器组件来处理所有异步的东西,并将道具传递给哑组件,例如,拥有多个容器组件,这些组件只关心它们需要的数据,以及获取它们需要的数据。我在这两种模式之间来回翻来覆去,发现它们各有优缺点:

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

  • pro:所有的isFetching道具和fetchSomeDependency()操作都可以在一个地方处理。
  • con:的缺点是,我发现自己不得不通过多个组件转发道具和回调,而树中间的某些组件最终会被绑在这上面。

下面是一个直观的问题示例,它显示了所需的关系--明智地:

代码语言:javascript
运行
复制
<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>

正如你所看到的,<MyModal /><MyModalContent />现在需要关注与它无关的道具,把它看作一种模式应该能够被重复使用,并且只关注一个模式的文体特性。

起初,上面的内容似乎很棒,但一旦我使用了100+组件,就会感到非常纠结,我发现这些顶级容器组件的复杂性不足以让我满意,因为它们中的大多数(在我正在开发的应用程序中)都依赖于来自3+ API请求的响应。

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

  • pro:完全消除了转发道具的需要。在某些情况下,这样做仍然是有意义的,但它要灵活得多。
  • pro:更容易重构。我感到惊讶的是,我如何能够在不破坏任何东西的情况下显着地移动和重构组件,而在另一种模式中,事情发生了很大的变化。
  • pro:每个容器组件的复杂性要小得多。我的mapStateToPropsmapDispatchToProps更特定于它所使用的组件的用途。
  • con:依赖于异步内容的任何组件本身总是需要处理isFetching状态。这增加了在单个容器组件中处理它的模式中不需要的复杂性。

因此,主要的困境是,如果我使用一个容器,那么根容器和叶组件之间的组件就会产生不必要的复杂性。如果我使用多容器,那么叶子组件就会变得更加复杂,最终会出现需要担心isFetching的按钮,尽管按钮不应该关心这个问题。

我想知道是否有人找到了避免这两种缺点的方法,如果是的话,你遵循的“经验法则”是什么来避免这一点?

谢谢!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-12-03 21:44:13

因此,自从我发布这个问题以来已经有两年多了,这段时间我一直在使用React/Redux。我现在的经验法则是:使用更多的容器,但是尝试以这样的方式编写组件,这样他们就不需要知道的情况了。

例如,下面是一个典型的示例,说明我以前如何构建待办事项列表:

代码语言:javascript
运行
复制
  function Todos({ isFetching, items }) {
    if (isFetching) return <div>Loading...</div>

    return (
      <ul>
        {items.map(item => 
          <li key={item.id}>...</li>
        )}
      </ul>
    )
  }

现在我会做一些更像:

代码语言:javascript
运行
复制
  function Todos({ items }) {
    if (!items.length) return <div>No items!</div>

    return (
      <ul>
        {items.map(item => 
          <li key={item.id}>...</li>
        )}
      </ul>
    )
  }

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

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

  1. 例如,我需要防止第二次单击提交按钮,从而进行API调用,在这种情况下,道具应该被称为disableSubmit,而不是isFetching,或者
  2. 在等待异步响应时,我希望显式地显示加载程序。

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

原因是,在上面的示例中,假设您正在轮询新的待办事项,或者当您添加一个todo时,您将“重新获取”这些待办事项。在第一个例子中会发生的是,每次发生这种情况,待办事项就会消失,并被替换为“装载.”。经常发生。

但是,在与isFetching无关的第二个示例中,只需添加/删除新项。在我看来,这是更好的UX。

实际上,在发布这篇文章之前,我研究了我编写的一个exchange接口的所有UI代码,这个界面非常复杂,没有找到一个将isFetching连接到我编写的容器组件的实例。

票数 1
EN

Stack Overflow用户

发布于 2016-09-07 20:12:48

我一直认为,将容器放在逻辑组件组的最上面,而不是根/app组件。

因此,如果我们有一个简单的搜索应用程序,可以显示结果,并假设组件是这样的

代码语言:javascript
运行
复制
<Root> <- setup the app
  <App>
    <Search/> <- search input
    <Results/> <- results table
  </App>
</Root>

我会让SearchResults redux知道容器。因为react组件应该是可组合的。您可能有需要显示ResultsSearch的其他组件或页面。如果将数据获取和存储意识委托给根组件或app组件,则会使组件相互依赖/依赖。当您必须实现更改时,这会使更改变得更加困难,现在您必须更改所有使用它们的位置。

这方面的例外可能是如果组件之间确实有非常紧密耦合的逻辑。即使如此,我想说的是,您应该创建一个容器来包装紧密耦合的组件,因为它们将无法在没有彼此的情况下实际使用。

票数 2
EN

Stack Overflow用户

发布于 2017-06-02 11:56:15

Redux作者Dan建议您在需要容器组件时使用它们。也就是说,一旦组件之间有太多的道具连接,就该使用容器了。

他称其为“正在进行的重构过程”。

参见本文:abramov/smart-and-dumb-components-7ca2f9a7c7d0

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39377712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档