JavaScript – 将商店状态作为道具传递,或者每个组件访问全球商店?

我有点混淆:“渲染整个应用程序”和“传递状态到子组件”。

示例1:

我有一个包含AppComponent和TodosListComponent的todos应用程序。 AppComponent从商店中获取todos数组,并将其作为属性传递给TodosListComponent。

示例2:

我有一个巨大的应用程序与许多国家。我有50个组件构建我的应用程序。我想从AppComponent的所有商店通过所有50个组件的所有状态?

所以我想知道什么是公约?让我让个别组件直接听他们关心的商店更有意义。优点是只有单个组件复习,但是为什么“整个应用程序复归国家变化”的概念呢?

每个的利弊是什么?常见的惯例是什么?

有几种方法可以解决这个问题。我认为它们都是有效的,并有自己的权衡。

获取所有的状态并将其传递给孩子们

这是你特别提到的技术。使用这种方法,您将有一些功能或方法可用于顶级组件,将所有数据从商店转换为“大袋状态”,然后您将选择性地将这些数据传递给子组件。如果这些组件有自己的孩子,他们将根据需要传递。

这种方法的优点在于它使事情通常易于调试。如果您必须更改从商店检索状态的方式,则只需在顶级组件中更改状态即可,只要它以相同的名称传递,其他组件将“正常工作”。 “如果某些数据错误,您只需要在一个地方找出原因。

这种技术的缺点是我所说的“道具爆炸” – 你可以最终传递很多属性。我在中等大小的应用程序中使用这种方法,顶层应用程序组件的代码片段如下所示:

<section id="col-left">
  <Filters loading={this.state.loading}
            events={this.state.events}
            playbackRate={this.state.videoPlayback.playbackRate}
            autoPlayAudio={this.state.audioPlayback.autoPlay}
            role={this.state.role} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo videoUuid={this.state.session.recording_uuid}
                lowQualityVideo={this.state.session.low_quality_video_exists}
                playbackRate={this.state.videoPlayback.playbackRate} />
  <section id="transcript">
    <Transcript loading={this.state.loading}
                events={this.state.events}
                currentEvents={this.state.currentEvents}
                selection={this.state.selection}
                users={this.state.session.enrolled_users}
                confirmedHcs={this.state.ui.confirmedHcs}

                currentTime={this.state.videoPlayback.position}
                playing={this.state.videoPlayback.playing} />
  </section>
</section>

特别地,顶层和一些最终的孩子之间可能有很多组件,除了传递之外,它们对数据什么都不做,更紧密地将这些组件耦合到它们在层次结构中的位置。

总的来说,我喜欢这种技术提供的可调试性,但是随着应用程序越来越大,复杂度越来越高,我发现只有一个顶级组件才是这样做的。

获取所有状态并将其作为一个对象传递

Facebook的开发人员之一提到了这种技术。在这里,你会得到一大堆状态,就像上面一样,但是你会传递整个事情(或者整个事情的整个部分),而不是单独的属性。通过在子组件中使用React.PropTypes.shape,可以确保正确的属性被传递。

上行是你通过的方式更少的财产;上面的例子可能看起来更像这样:

<section id="col-left">
  <Filters state={this.state} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo session={this.state.session}
                playback={this.state.videoPlayback} />
  <section id="transcript">
    <Transcript state={this.state} />
  </section>
</section>

缺点是处理国家形状的变化有点困难;而不仅仅是更改顶级组件,您将不得不随时追踪使用这些数据,并更改组件访问该属性的方式。此外,shouldComponentUpdate可能会变得有些棘手的实现。

允许组件获取自己的状态

在频谱的另一端,您可以根据商店更改事件授予特定于应用程序(即不可重用的)子组件来访问商店并建立自己的状态。构建这样的状态的组件有时被称为“控制器视图”,或者更常见的是“容器组件”。

当然,它的优势在于,您根本无需处理传递属性(除更改处理程序和更多可重用组件的属性之外)。

不过,不利之处在于,您的组件与商店更为紧密相连 – 更改商店或提供的数据(或通过它们提供该数据的接口)可能会迫使您重新访问更多数量的组件的代码。

另外,如在评论中提到的,这可能会使服务器渲染更困难。如果您仅使用属性(特别是仅在顶级),则可以更轻松地将其传输到客户端,并使用相同的属性重新初始化React。通过允许商店确定自己的数据,您需要以某种方式将该数据注入商店,以允许组件获取该数据。

通常的方法和我现在通常使用的方法是使应用程序中的每个组件只依靠道具进行全局应用程序状态,然后决定是否更有意义(1)将它们直接连接到磁链,一个容器,或(2)允许道具从一些父容器传递。

有一些抽象可以用来使这些技术更可行。例如,Facebook开发人员在a comment on Hacker News年有这样的说法:

Now all your data is in stores, but how do you get it into the specific component that needs it? We started with large top level components which pull all the data needed for their children, and pass it down through props. This leads to a lot of cruft and irrelevant code in the intermediate components. What we settled on, for the most part, is components declaring and fetching the data they need themselves, except for some small, more generic components. Since most of our data is fetched asynchronously and cached, we’ve created mixins that make it easy to declare which data your component needs, and hook the fetching and listening for updates into the lifecycle methods (componentWillMount, etc).

翻译自:https://stackoverflow.com/questions/26563933/passing-store-state-as-props-or-each-component-accessing-global-stores

转载注明原文:JavaScript – 将商店状态作为道具传递,或者每个组件访问全球商店?