反应,流量,状态和商店

时间:2014-05-29 10:39:10

标签: reactjs reactjs-flux

我发现todo flux app的示例有点缺乏,所以我试图通过开发一个学习和实验的应用程序来解决问题。

该应用程序是一个拖放水果篮组织者。我有几个篮子,可以在它们之间拖着各种水果。您可以通过单击突出显示一块水果,最后拖动的项目将保持突出显示。

基于此,我有3家商店:

  • FruitStore
  • BasketStore
  • AppStateStore - 跟踪上次点击的和上次拖动的水果

当用户操作发生时,如果点击了水果,则AppStateStore会调度和处理FruitAction;如果水果已被移动到另一个篮子,则由AppStateStore处理。

主AppView组件侦听来自FruitStore和AppStateStore的更改事件并重新呈现。

我的问题是:

  • 对于这种情况,这是一个很好的方法吗?
  • AppView应该收听多个商店吗?我应该如何防止AppView连续多次渲染?现在,当一个水果被移动时,FruitStore和AppStateStore都会触发更改事件,导致连续两个渲染。
  • React站点上的Flux文章显示了调度操作对象的视图(例如AppDispatcher.dispatch(TodoActions.updateText()))但如果操作调度自身(例如只是FruitActions.moveBasket())并且会更好AppView没有意识到AppDispatcher?
  • 目前只有AppView会监听商店,但是如果要突出显示,各个Fruit组件是否应该监听AppStateStore才能自行重新呈现?
  • 是否有更完整的Flux架构示例或类似内容?

2 个答案:

答案 0 :(得分:13)

  • 这种方法听起来很稳固。我会为每次互动创建完全不同的动作,例如FruitClickedFruitDragged都可以是行动,商店会关注他们关心的行为。
  • AppView应该收听从中获取数据的所有商店。如果你在同一个标​​记中多次调用setState,React会智能地合并它们,因此你实际上不会多次渲染。
  • React网站上的文章确实讨论了在Creating Semantic Actions下发送自己的行为。在代码块中,页面上有几个滚动长度,您可以看到代码:

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • 本文还讨论了哪些组件应该在Listening to Changes with a Controller-View中监听商店:

      

    我们需要在组件层次结构顶部附近的React组件来监听商店中的更改。在一个更大的应用程序中,我们将拥有更多这些监听组件,可能对于页面的每个部分都有一个。在Facebook的广告制作工具中,我们有许多类似控制器的视图,每个视图都管理UI的特定部分。在Lookback视频编辑器中,我们只有两个:一个用于动画预览,一个用于图像选择界面。

      

    有时我们可能需要在层次结构中更深层地添加其他控制器视图以保持组件简单。这可以帮助我们更好地封装与特定数据域相关的层次结构的一部分。但请注意,层次结构中更深层次的控制器视图可能会通过为数据流引入新的,可能相互冲突的入口点来违反单一数据流。在决定是否添加深度控制器视图时,将更简单组件的增益与流入层次结构中的不同点的多个数据更新的复杂性进行平衡。这些多个数据更新可能会导致奇怪的效果,React的渲染方法会被来自不同控制器视图的更新重复调用,这可能会增加调试的难度。

  • 如果您对磁通体系结构感兴趣,您可能会对Fluxxor感兴趣(免责声明:我写过它),它(希望)有助于构建基于磁通的应用程序。它有一个更强大的调度程序和一些其他更改(例如非全局存储/操作,React mixins),在许多情况下使事情变得更容易。

答案 1 :(得分:5)

如果不理解应用程序,很难说这种方法是否合适。

然而,在我看来,点击水果应该由FruitStore处理。也就是说,一种水果已经获得了活跃的状态,已经变得可以拖延。如果这会以某种方式影响整个应用程序,那么这可能会导致AppStateStore发生变化。同样地,将水果从一个篮子移动到另一个篮子似乎是BasketStore的领域。

我想像FruitStore包含这样的私有数据结构:

var _fruit = {
  1234: {
    id: '1234',
    type: 'apple',
    active: false
  },
  2345: {
    id: '2345',
    type: 'orange',
    active: false
  },
  3456: {
    id: '3456',
    type: 'apple',
    active: false
  }
};

我认为BasketStore有一个私有数据结构,如下所示:

var _baskets = {
  4321: {
    id: '4321',
    name: 'Josephine\'s Basket',
    fruitIDs: [
      1234,
      2345
    ]
  },
  5432: {
    id: '5432',
    name: 'Harold\'s Basket',
    fruitIDs: [
      3456
    ]
  }
};
因此,水果"活跃" state由FruitStore管理,篮子的内容由BasketStore管理。

因此,如果适用于您的应用程序,AppView可以收听这两个商店。如上所述,重复调用render()方法的成本非常低。这并不会触及每次通话中的DOM - 这是React最大的优势之一。反过来,智能会智能地批量调用,只更新"脏" DOM的一部分,如果存在的话。

但也许您可能希望将篮子变成控制器视图。如果您确实选择将水果作为控制器视图,请务必清除componentWillUnmount()中的监听器,因为从篮子到篮子的水果移动可能需要销毁它们并重新创建。我认为在篮下听力更有意义,但同样,我也不太了解你的应用。

回答你的上一个问题:

  

是否有更完整的Flux架构示例或类似内容?

Facebook的工程师正在开发一个更复杂的应用程序示例,现在将展示waitFor()和服务器端持久存储的使用。我们希望尽快发布。

相关问题