为什么要使用Redux而不是Facebook Flux?

时间:2015-09-08 15:05:15

标签: javascript reactjs reactjs-flux flux redux

我已阅读this answerreducing boilerplate,查看了几个GitHub示例,甚至尝试了redux(todo apps)。

据我了解,official redux doc motivations提供了与传统MVC架构相比的优点。但它没有提供问题的答案:

为什么你应该使用Redux而不是Facebook Flux?

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

如果我说redux对于来自函数式语言的人来说是一种变化,我是对的吗?

要回答这个问题,您可以比较实施redux在通量与减少量上的动机点的复杂性。

以下是official redux doc motivations的动机要点:

  1. 处理乐观的更新(据我所知,它几乎不取决于第5点。难道在facebook flux中实现它吗?
  2. 在服务器上渲染( facebook flux也可以这样做。与redux相比有什么好处?
  3. 在执行路径转换之前获取数据(为什么在facebook中无法实现?有什么好处?
  4. 热重新加载(可以使用React Hot Reload。为什么我们需要redux?
  5. 撤消/重做功能
  6. 还有其他什么意思吗?就像坚持国家......

8 个答案:

答案 0 :(得分:1959)

Redux作者在这里!

Redux不是 与Flux不同。总体而言,它具有相同的架构,但Redux能够通过使用Flux使用回调注册的功能组合来削减一些复杂角落。

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

还原剂组合物

以分页为例。我的Flux + React Router example处理分页,但代码很糟糕。其中一个可怕的原因是 Flux使得跨商店重用功能变得不自然。如果两个商店需要处理分页以响应不同的操作,他们要么需要继承共同的基本存储(糟糕!当您使用继承时,您将自己锁定到特定设计中),或者从事件处理程序中调用外部定义的函数,这将需要以某种方式操作Flux存储的私有状态。整件事情很混乱(虽然绝对是可能的)。

另一方面,由于减速剂成分,Redux分页很自然。它的减速器一直向下,所以你可以写reducer factory that generates pagination reducers然后use it in your reducer tree。它之所以如此简单的关键是因为在Flux中,商店是平的,但在Redux中,reducer可以通过功能组合嵌套,就像React组件可以嵌套一样。

此模式还支持非用户代码undo/redo等精彩功能。 您能想象将Undo / Redo插入到两行代码的Flux应用程序中吗?几乎不。由于减速器组成模式,使用Redux,它是 - 重要的。我需要强调其中没有什么新鲜事 - 这是Elm Architecture中开创并详细描述的模式,它本身受到Flux的影响。

服务器渲染

人们使用Flux在服务器上渲染得很好,但是看到我们有20个Flux库,每个都试图让服务器呈现“更容易”,或许Flux在服务器上有一些粗糙的边缘。事实是Facebook并没有做太多的服务器渲染,因此他们并没有非常关注它,而是依靠生态系统来简化它。

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

您需要在Flux中解决以下问题(您自己或在您最喜欢的Flux库的帮助下,例如FlummoxAlt):

  • 如果商店是类,我如何根据请求使用调度程序创建和销毁它们?我什么时候注册商店?
  • 如何保存商店中的数据,然后在客户端进行补水?我需要为此实现特殊方法吗?

不可否认,Flux框架(不是vanilla Flux)可以解决这些问题,但我发现它们过于复杂。例如,Flummox asks you to implement serialize() and deserialize() in your stores。 Alt通过提供{J}树中自动序列化状态的takeSnapshot()来解决这个问题。

Redux更进一步:因为只有一个商店(由许多减速机管理),你不需要任何特殊的API来管理(重新)水合作用。你不要&# 39;需要“冲洗”或“保湿”商店 - 只有一个商店,您可以读取其当前状态,或创建一个新状态的商店。每个请求都有一个单独的商店实例。 Read more about server rendering with Redux.

同样,这是一个可能在Flux和Redux中都有可能的情况,但是Flux库通过引入大量的API和约定来解决这个问题,而且Redux甚至不必解决它,因为它没有&#39由于概念上的简单性,首先出现了这个问题。

开发者体验

我实际上并不打算让Redux成为一个受欢迎的Flux库 - 我在写ReactEurope talk on hot reloading with time travel时正在编写它。我有一个主要目标:可以动态更改减速器代码,甚至可以通过交叉操作“改变过去”,并查看重新计算的状态。

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

当Redux需要重新加载reducer代码时,它会调用replaceReducer(),并且应用程序将使用新代码运行。在Flux中,数据和功能与Flux商店纠缠在一起,因此您无法“只更换功能”。此外,您必须以某种方式使用Dispatcher重新注册新版本 - Redux甚至没有。

生态系统

Redux有一个rich and fast-growing ecosystem。这是因为它提供了一些扩展点,例如middleware。它的设计考虑了loggingPromises支持,Observablesroutingimmutability dev checkspersistence等用例。并非所有这些都会变得有用,但是访问一组可以轻松组合起来协同工作的工具真的很不错。

简单

Redux保留了Flux的所有好处(记录和重放动作,单向数据流,依赖变异),并增加了新的好处(简单的撤消重做,热重新加载),而不引入Dispatcher和商店注册。

保持简单非常重要,因为它可以在您实现更高级别的抽象时保持理智。

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

您实际上可以阅读并理解Redux的所有内容。

另见my answer on downsides of using Redux compared to Flux

答案 1 :(得分:101)

In Quora, somebody says

  

首先,完全可以使用React编写应用程序   通量。

我创建的这个视觉图是为了快速查看两者,对于那些不想阅读整个解释的人来说,这可能是一个快速的答案: Flux vs Redux

但如果您仍然对此了解更多,请继续阅读。

  

我相信你应该从纯粹的React开始,然后学习Redux和Flux。   在你有了React的真实经验之后,你会看到   Redux是否对你有帮助。

     

也许你会觉得Redux完全适合你的应用,也许你   会发现,Redux正试图解决你不是的问题   真的很有经验。

     

如果您直接使用Redux,最终可能会过度设计   代码,代码更难维护,甚至更多的错误   终极版。

来自Redux docs

  

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

     

管理这个不断变化的状态很难。如果模型可以更新   另一个模型,然后视图可以更新模型,更新另一个模型   模型,反过来,这可能会导致另一个视图更新。在某些   请注意,您不再了解您的应用中发生的事情   失去对其状态的时间,原因和方式的控制。当一个系统   是不透明和不确定的,很难重现错误或添加   新功能。

     

好像这还不够糟糕,请考虑新的要求   在前端产品开发中很常见。作为开发人员,我们是   期望处理乐观更新,服务器端呈现,提取   执行路由转换之前的数据,等等。我们发现自己   试图管理我们从未必须处理的复杂性   之前,我们不可避免地提出这样一个问题:是时候放弃了吗?该   答案是否。

     

这种复杂性很难处理,因为我们混合了两个概念   这是人类思维难以推理的原因:突变和   异步性。我称他们为Mentos和Coke。两者都很棒   分开,但他们在一起造成一团糟。像React这样的图书馆   尝试通过删除两者来解决视图层中的此问题   异步和直接DOM操作。但是,管理状态   您的数据由您自己决定。这就是Redux的用武之地。

     

追随Flux,CQRS和Event Sourcing,Redux的脚步   试图通过强加某些来预测状态突变   更新如何以及何时发生的限制。这些限制   反映在Redux的三个原则中。

同样来自Redux docs

  

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

     

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

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

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

     

要更改状态中的某些内容,您需要发送操作。一个   action是一个普通的JavaScript对象(请注意我们如何不引入任何内容   魔术?)描述发生了什么。以下是一些示例操作:

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

强制将每个更改描述为一个动作让我们拥有一个   清楚地了解应用程序中发生了什么。如果有的话   改变了,我们知道它为什么会改变。行动就像是面包屑   已经发生了。最后,为了将状态和行动联系起来,我们写了一个   函数称为reducer。再一次,没有什么神奇之处 - 它只是一个   将state和action作为参数的函数,并返回   该应用的下一个状态。要为a编写这样的函数会很困难   大应用程序,所以我们编写管理州的部分的较小功能:

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,或任何魔术。

答案 2 :(得分:57)

你可能最好开始阅读Dan Abramov的这篇文章,他在撰写redux时讨论了Flux的各种实现及其权衡: The Evolution of Flux Frameworks

其次,您链接的动机页面并没有真正讨论Redux的动机,而是Flux(和React)背后的动机。 Three Principles更具特定于Redux,但仍然没有处理与标准Flux架构的实现差异。

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

答案 3 :(得分:27)

我是早期采用者,并使用Facebook Flux库实施了一个中型单页应用程序。

由于我在谈话中迟到了,我只是指出,尽管我最好的希望Facebook似乎认为他们的Flux实施是一个概念证明,它从未得到应有的关注。

我鼓励你玩它,因为它暴露了Flux架构的更多内部工作,这是非常有教育意义的,但同时它没有提供像Redux这样的库提供的许​​多好处(这对小型项目来说并不重要,但对大型项目来说非常有价值)。

我们决定继续前进,我们将转向Redux,我建议你也这样做;)

答案 4 :(得分:20)

以下是Redux over Flux的简单解释。 Redux没有调度程序。它依赖于名为reducers的纯函数。它不需要调度员。每个操作由一个或多个Reducer处理以更新单个存储。由于数据是不可变的,因此reducers返回更新商店enter image description here

的新更新状态

了解更多信息Flux vs Redux

答案 5 :(得分:6)

我使用Flux工作了很长时间,现在使用Redux已经很长时间了。正如丹指出的那样,两种架构都没有那么不同。事情是,Redux使事情更简单,更清洁。它会在Flux上教你一些东西。例如,Flux是单向数据流的完美示例。我们将数据,操作和视图层分开的关注点分离。在Redux中我们有相同的东西,但我们也学习了不变性和纯函数。

答案 6 :(得分:5)

从一个新的react / redux采用者从ExtJS(几年)于2018年中期开始迁移:

向后滑下redux学习曲线后,我遇到了相同的问题,并认为纯通量像OP一样简单。

我很快看到了redux相对于通量的好处,如上面的答案所述,并且正在将其用于我的第一个应用程序中。

在再次抓住样板时,我尝试了一些 other 状态管理库,发现的最好的是rematch

它比香草Redux直观得多,它减少了90%的样板,减少了我花在Redux上的时间的75%(我认为图书馆应该这样做) ,我马上就可以使用几个企业应用程序。

它也可以使用相同的redux工具运行。这是good article,涵盖了一些好处。

因此,对于到达此SO职位搜索“更简单的redux”的任何人,我建议尝试使用它作为redux的一种简单替代方法,它具有所有优势和1/4的样板。

答案 7 :(得分:0)

根据本文: https://medium.freecodecamp.org/a-realworld-comparison-of-front-end-frameworks-with-benchmarks-2019-update-4be0d3c78075

最好使用MobX来管理应用程序中的数据以获得更好的性能,而不是Redux。