为什么在Facebook上使用Redux通量?

我读过这个答案,减少了样板,查看了几个GitHub的例子,甚至尝试了一点点(todo应用程序)。

据我所知,官方的redux doc动机提供了与传统MVC架构相比的优点。 但它没有提供对这个问题的答案:

为什么你应该使用Facebook上的Flux使用Redux?

这只是一个编程风格的问题:功能与非功能? 或者问题出在redux方法中的能力/开发工具? 也许缩放? 还是测试?

如果我说,redux对于来自功能语言的人来说是一种流量,我是对的吗?

要回答这个问题,你可以比较实现redux在flux和redux上的动机点的复杂性。

以下是来自官方REDX DOC动机的动机:

  • 处理乐观的更新(据我所知,它很难取决于第五点,难以在fb流量中实现它)?
  • 在服务器上渲染(fb flux也可以做到这一点,与redux相比有什么好处?)
  • 在执行路由转换之前获取数据(为什么在fb flux中无法实现?有什么好处?)
  • 热重新加载(React Hot Reload可能会出现这种情况,为什么我们需要重新加载?)
  • 撤销/重做功能
  • 其他要点? 像持久状态一样......

  • Redux的作者在这里!

    Redux和Flux没有什么不同。 总体而言,它具有相同的体系结构,但Redux能够通过使用Flux使用回调注册的功能组合来削减一些复杂性。

    Redux并没有根本的区别,但我发现它使某些抽象更容易,或者至少可以实现,这在Flux中很难实现或无法实现。

    还原剂组成

    以分页为例。 我的Flux + React Router示例处理分页,但代码很糟糕。 其糟糕的原因之一是Flux在商店间重复使用功能使其不自然。 如果两个商店需要处理分页以响应不同的动作,他们或者需要从一个通用的基本商店继承(当你使用继承时,你将自己锁定在特定的设计中),或者从处理函数调用一个函数,将需要以某种方式在Flux商店的私人州进行操作。 整个事情是混乱的(尽管绝对在可能的范围内)。

    另一方面,由于还原剂成分的原因,Redux分页是自然的。 它是减速器,所以你可以编写一个减速器工厂来生成分页减速器,然后在减速器树中使用它。 关键是为什么它很容易,因为在Flux中,商店是平坦的,但在Redux中,reducer可以通过功能组合嵌套,就像React组件可以嵌套一样。

    这种模式还支持非用户代码撤销/重做等美妙功能。 你能想象将Undo / Redo插入到两行代码的Flux应用程序中吗? 几乎不。 随着Redux,它是 - 重要的 ,由于减速机组成模式。 我需要强调的是这并不是什么新鲜事 - 这是Elm Architecture开创并详细描述的模式,它本身受Flux的影响。

    服务器渲染

    人们已经使用Flux在服务器上渲染,但是看到我们有20个Flux库,每个都试图让服务器渲染“更容易”,可能Flux在服务器上有一些粗糙的边缘。 事实是,Facebook并没有做太多的服务器渲染,所以他们一直不关心它,并依靠生态系统来使它更容易。

    在传统的Flux中,商店是单身人士。 这意味着很难将服务器上不同请求的数据分开。 不是不可能的,但很难。 这就是为什么大多数Flux库(以及新的Flux Utils)现在建议您使用类而不是单例,因此您可以为每个请求实例化商店。

    您仍然需要在Flux中解决以下问题(无论是您自己还是在您最喜欢的Flux库(如Flummox或Alt)的帮助下):

  • 如果商店是类,那么如何根据请求创建和销毁它们? 我什么时候注册商店?
  • 我如何从商店补充水分,然后在客户端补充水分? 我需要为此实现特殊的方法吗?
  • 无可否认,Flux框架(不是vanilla Flux)可以解决这些问题,但我发现它们过于复杂。 例如,Flummox要求您在商店中实现serialize()和deserialize deserialize() 。 Alt可以通过提供takeSnapshot()来解决这个问题,它可以在JSON树中自动序列化你的状态。

    Redux更进一步: 由于只有一家商店(由许多缩减者管理),因此您不需要任何特殊的API来管理(再)保湿。 您不需要“冲洗”或“保存”商店 - 只有一家商店,您可以阅读其当前状态,或创建一个新的商店并拥有新的状态。 每个请求都有一个独立的商店实例。 使用Redux阅读有关服务器呈现的更多信息

    再次,这是Flux和Redux中可能的情况,但Flux库通过引入大量的API和约定来解决这个问题,并且Redux甚至不需要解决它,因为它没有这个问题首先归功于概念简单。

    开发者体验

    我实际上并不打算让Redux成为一个受欢迎的Flux库 - 我是在编写ReactEurope关于时间旅行热重新加载的谈话时写的。 我有一个主要目标: 可以动态更改减速器代码,甚至通过删除操作来“改变过去”,并查看重新计算的状态。

    我还没有看到能够做到这一点的单个Flux库。 React Hot Loader也不会让你这样做 - 事实上,如果你编辑Flux商店,它会中断,因为它不知道如何处理它们。

    当Redux需要重新加载Reducer代码时,它会调用replaceReducer() ,并且该应用程序将使用新代码运行。 在Flux中,数据和功能被Flux商店纠缠,所以你不能“仅仅替换功能”。 此外,您必须以某种方式重新注册Dispatcher的新版本 - 这是Redux甚至没有的。

    生态系统

    Redux拥有丰富且快速增长的生态系统。 这是因为它提供了一些扩展点,例如中间件。 它的设计与记录,支持Promise,Observables,路由,不变性开发检查,持久性等用例有关。 并不是所有这些都会变得有用,但能够访问一系列可轻松组合起来共同工作的工具是非常好的。

    简单

    Redux保留了Flux的所有优点(录制和回放操作,单向数据流,相关突变),并且增加了新的优点(简单的撤销 - 重做,热重载),无需引入分派器和商店注册。

    保持简单是很重要的,因为它让你保持理智,同时实现更高层次的抽象。

    与大多数Flux库不同,Redux API表面很小。 如果您删除了开发人员警告,注释和完整性检查,则它是99行。 没有棘手的异步代码来调试。

    你可以真正阅读并理解Redux的所有内容。


    另请参阅我对使用Redux和Flux进行比较的缺点的回答。


    在Quora,有人说:

    首先,完全可以在没有Flux的情况下使用React编写应用程序。

    我创建的这个视觉图也展示了这两个视图,对于不想阅读整个解释的人来说,这可能是一个快速回答: Flux vs Redux

    但如果你仍然有兴趣知道更多,请继续阅读。

    我相信你应该从纯粹的React开始,然后学习Redux和Flux。 在使用React之后,您将看到Redux是否对您有所帮助。

    也许你会觉得Redux正好适合你的应用程序,也许你会发现,Redux正在试图解决你并没有真正遇到的问题。

    如果直接从Redux开始,那么最终可能会出现过度设计的代码,难以维护的代码以及更多的错误,而不是Redux。

    来自Redux文档:

    动机
    随着对JavaScript单页应用程序的要求变得越来越复杂,我们的代码必须比以前更多地处理状态。 此状态可以包括服务器响应和缓存数据,以及本地创建的尚未保存到服务器的数据。 UI状态的复杂性也在增加,因为我们需要管理活动路线,选定标签,旋钮,分页控件等。

    管理这个不断变化的状态是困难的。 如果一个模型可以更新另一个模型,那么一个视图可以更新一个模型,该模型会更新另一个模型,而这又可能导致另一个视图更新。 在某种程度上,您不再理解您的应用程序会发生什么情况,因为您已经失去了对其状态的何时,为何和如何的控制。 当系统不透明且不确定时,很难重现错误或添加新功能。

    好像这还不够糟糕,请考虑新的要求在前端产品开发中变得常见。 作为开发人员,我们需要处理乐观的更新,服务器端渲染,在执行路由转换之前获取数据等等。 我们发现自己试图去处理一个我们以前从来没有处理过的复杂问题,而我们不可避免地提出这样一个问题:是否该放弃了? 答案是不。

    这种复杂性很难处理,因为我们正在混合两个对人类头脑非常难以推理的概念:突变和异步性。 我把它们叫做曼托斯和可乐。 两人分开时会很好,但他们一起创造一团糟。 像React这样的库试图通过去除异步和直接DOM操作来解决视图层中的这个问题。 但是,管理数据的状态由您决定。 这是Redux进来的地方。

    继Flux,CQRS和Event Sourcing之后,Redux试图通过对更新可能发生的方式和时间施加一定的限制来预测状态变化。 这些限制反映在Redux的三个原则中。

    同样来自Redux文档:

    核心概念
    Redux本身非常简单。

    想象一下,你的应用程序的状态被描述为一个普通的对象。 例如,待办事项应用的状态可能如下所示:

    {
      todos: [{
        text: 'Eat food',
        completed: true
      }, {
        text: 'Exercise',
        completed: false
      }],
      visibilityFilter: 'SHOW_COMPLETED'
    }
    

    这个对象就像一个“模型”,除了没有setter。 这是因为代码的不同部分不能任意改变状态,导致难以重现的错误。

    要改变这个状态,你需要发送一个动作。 一个动作是一个普通的JavaScript对象(注意我们如何不引入任何魔法?),它描述了发生的事情。 以下是一些示例操作:

    { type: 'ADD_TODO', text: 'Go to swimming pool' }
    { type: 'TOGGLE_TODO', index: 1 }
    { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
    

    强制将每一项变更都描述为一项行动,让我们清楚了解应用程序正在发生的事情。 如果有什么改变,我们知道它为什么改变。 行动就像发生了什么事情的面包屑。 最后,为了将状态和动作绑定在一起,我们编写了一个名为reducer的函数。 再说一遍,它没有任何魔力 - 它只是一个将状态和动作作为参数的函数,并返回应用程序的下一个状态。 为大型应用程序编写这样的功能将很难,因此我们编写管理部分状态的较小函数:

    function visibilityFilter(state = 'SHOW_ALL', action) {
      if (action.type === 'SET_VISIBILITY_FILTER') {
        return action.filter;
      } else {
        return state;
      }
    }
    
    function todos(state = [], action) {
      switch (action.type) {
      case 'ADD_TODO':
        return state.concat([{ text: action.text, completed: false }]);
      case 'TOGGLE_TODO':
        return state.map((todo, index) =>
          action.index === index ?
            { text: todo.text, completed: !todo.completed } :
            todo
       )
      default:
        return state;
      }
    }
    

    然后我们编写另一个reducer,通过调用这两个reducer来查找相应的状态键来管理我们的应用程序的完整状态:

    function todoApp(state = {}, action) {
      return {
        todos: todos(state.todos, action),
        visibilityFilter: visibilityFilter(state.visibilityFilter, action)
      };
    }
    

    这基本上是Redux的整个想法。 请注意,我们尚未使用任何Redux API。 它提供了一些用于简化这种模式的实用程序,但主要想法是描述如何随着时间的推移更新状态以响应操作对象,并且您编写的代码中有90%只是普通的JavaScript,没有使用Redux本身,API或任何魔法。


    您可能最好从Dan Abramov的这篇文章开始阅读,他在讨论Flux的各种实现及其在编写redux时的权衡:Flux框架的演变

    其次,您链接到的动机页面并不真正讨论Redux的动机,以及Flux(和React)背后的动机。 这三个原则更具有Redux特色,但仍然没有涉及与Flux标准体系结构的实施差异。

    基本上,Flux有多个商店,用于响应UI / API与组件的交互来计算状态更改,并将这些更改作为组件可订阅的事件广播。 在Redux中,每个组件订阅的商店只有一个。 IMO至少像Redux一样,通过统一数据流(或者减少,如Redux所说),将数据流返回到组件,从而进一步简化和统一数据流 - 而Flux专注于统一数据流的另一端 - 查看模型。

    链接地址: http://www.djcxy.com/p/51665.html

    上一篇: Why use Redux over Facebook Flux?

    下一篇: Use of "global" keyword in Python