为什么在Facebook Flux上使用Redux?

我读过这个答案还原样板,看了几个GitHub示例,甚至尝试了一点redux(待办事项应用程序)。

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

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

这仅仅是编程风格的问题吗:函数式与非函数式?或者问题在于遵循Redux方法的能力/开发工具?也许是扩展?还是测试?

如果我说redux是来自函数式语言的人的流量,我是对的吗?

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

以下是来自官方redux doc动机的动机点:

  1. 处理乐观的更新(据我所知,它几乎不依赖于第5点。在facebook流通量中实现它很难吗?
  2. 在服务器上渲染(Facebook的通量也可以做到这一点。与Redux相比有什么好处吗?
  3. 在执行路由转换之前获取数据(为什么它不能在facebook通量中实现?有什么好处?
  4. 热重新加载(这是可能的React Hot Reload。为什么我们需要redux?
  5. 撤消/重做功能
  6. 还有其他要点吗?比如持久化状态…
279068 次浏览

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

其次,您链接到的动机页面并没有真正讨论Redux的动机,而是讨论Flux(和React)背后的动机。三项原则更具Redux针对性,尽管仍然没有处理与标准Flux架构的实现差异。

基本上,Flux有多个存储,它们响应与组件的UI/API交互来计算状态更改,并将这些更改作为组件可以订阅的事件广播。在Redux中,每个组件只订阅一个存储。在我看来,至少Redux通过统一(或减少,正如Redux所说)数据流回组件来进一步简化和统一数据流——而Flux专注于统一数据流的另一边——视图到模型。

Redux作者在这里!

Redux与Flux没有不同。总的来说,它具有相同的架构,但Redux能够通过使用Flux使用回调注册的功能组合来减少一些复杂性。

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

减速机组成

以分页为例,我的Flux+React路由器示例处理分页,但这方面的代码很糟糕。之所以糟糕的原因之一是Flux使得跨商店重用功能变得不自然。如果两个商店需要响应不同的操作来处理分页,他们要么需要从共同的基存储继承(糟糕!当你使用继承时,你将自己锁定在特定的设计中),要么从事件处理程序中调用一个外部定义的函数,这将需要以某种方式在Flux商店的私有状态上操作。整件事很混乱(尽管绝对在可能的范围内)。

另一方面,使用Redux分页是很自然的,这要归功于Redux组合。它是一直向下的Redux,所以你可以写一个生产分页减速机的减速机厂然后用在你的减速机树上。它如此容易的关键是因为在Flux中,存储是扁平的,但在Redux中,可以通过功能组合嵌套减速器,就像可以嵌套React组件一样。

这个模式还支持像no-user-code撤销/重做.你能想象将撤销/重做插入Flux应用程序是两行代码吗?几乎没有。使用Redux,它是这样的精彩特性,这要归功于Reduce er组合模式。我需要强调的是,它并没有什么新的东西——这是榆树建筑中开创并详细描述的模式,它本身就受到Flux的影响。

服务端渲染

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

在传统的Flux中,存储是单例的。这意味着很难为服务器上的不同请求分离数据。不是不可能,而是很难。这就是为什么大多数Flux库(以及新的FluxUtils)现在建议你使用类而不是单例,这样你就可以为每个请求实例化存储。

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

  • 如果存储是类,我如何根据请求使用调度器创建和销毁它们?我什么时候注册存储?
  • 如何对存储中的数据进行水合处理,然后在客户端上对其进行再水合处理?我是否需要为此实现特殊方法?

诚然,Flux框架(不是vanilla Flux)可以解决这些问题,但我觉得它们过于复杂。例如,Flummox要求您在商店中实现#0和#1。Alt通过提供#2自动序列化JSON树中的状态来解决这个问题。

Redux更进一步:由于只有一个商店(由许多减速机管理),因此您不需要任何特殊的API来管理(重新)水合作用。你不需要“刷新”或“水合”商店——只有一个商店,你可以读取它的当前状态,或者创建一个具有新状态的新商店。每个请求都有一个单独的商店实例。阅读有关使用Redux进行服务器渲染的更多信息。

同样,这是Flux和Redux中可能出现的情况,但Flux库通过引入大量API和约定来解决这个问题,而Redux甚至不必解决它,因为由于概念简单,它一开始就没有这个问题。

开发者体验

我实际上并不打算让Redux成为一个流行的Flux库——我在写我的ReactEurope谈论时间旅行的热重载时写了它。我有一个主要目标:使动态更改减速机代码成为可能,甚至可以通过划掉操作来“更改过去”,并查看正在重新计算的状态。

我还没有看到一个Flux库能够做到这一点。React Hot Loader也不允许你这样做——事实上,如果你编辑Flux存储,它就会崩溃,因为它不知道该怎么处理它们。

当Redux需要重新加载Repatcher代码时,它调用#0,应用程序使用新代码运行。在Flux中,数据和函数在Flux存储中纠缠在一起,所以你不能“只是替换函数”。此外,你必须以某种方式在Dispatcher重新注册新版本——这是Redux甚至没有的。

生态系统

Redux有一个丰富且快速增长的生态系统。这是因为它提供了一些扩展点,例如中间件。它的设计考虑了伐木等用例,支持Promises可观测数据路由选择不变性开发检查持久性等。并非所有这些都会有用,但能够访问一组可以轻松组合在一起工作的工具是件好事。

简单

Redux保留了Flux的所有优点(记录和重播操作、单向数据流、依赖突变),并增加了新的优点(轻松撤消重做、热重载),而无需引入Dispatcher和存储注册。

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

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

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


另见我对使用Redux与Flux相比的缺点的回答

我是一个早期切入并使用Facebook Flux库实现了一个中型单页应用程序。

由于我的谈话有点晚了,我只想指出,尽管我最大的希望Facebook似乎认为他们的Flux实现是概念的证明,但它从未得到应有的关注。

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

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

在Quora中,有人说

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

此外,我创建了这个可视化图表来显示两者的快速视图,可能是不想阅读整个解释的人的快速答案:Flux vs Redux

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

我相信你应该从纯React开始,然后学习Redux和Flux。在你对React有一些真正的经验之后,你会看到无论Redux对你有没有帮助。

也许你会觉得Redux完全适合你的应用程序,也许你会发现,Redux正在试图解决一个你没有的问题真正的体验

如果你直接从Redux开始,你可能最终会过度设计代码,代码更难维护,并且有更多的错误和比没有Redux。

Redux文档

动机
随着JavaScript单页应用程序的要求变得越来越复杂,我们的代码必须管理比以往更多的状态。这种状态可以包括服务器响应和缓存数据,以及本地创建的数据尚未持久化到服务器。UI状态也在增加在复杂性,因为我们需要管理活动路由,选定的选项卡,微调器、分页控件等。

管理这种不断变化的状态很难。如果模型可以更新另一个模型,那么一个视图可以更新一个模型,该模型更新另一个模型模型,而这反过来又可能导致另一个视图更新点,您不再了解您的应用程序中发生的事情失去了对其状态的时间、原因和方式的控制。当一个系统不透明且不确定,很难重现错误或添加新特性

如果这还不够糟糕,考虑新的需求在前端产品开发中常见。作为开发人员,我们预计处理乐观更新,服务端渲染,获取执行路由转换之前的数据,等等。我们发现自己试图管理一个我们从来没有处理过的复杂性之前,我们不可避免地会问这样一个问题:是时候放弃了吗?答案是否定的

这种复杂性很难处理,因为我们混合了两个概念这是人类很难推理的:突变和异步性。我称之为Mentos和Coke。当分开,但在一起会造成混乱。像React这样的库尝试通过删除两个视图层来解决这个问题异步和直接DOM操作。但是,管理你的数据留给你。这就是Redux的用武之地。

跟随Flux、CQRS和事件源的脚步,Redux试图通过施加某些更新发生的方式和时间的限制在Redux的三个原则中都有体现。

Redux文档开始:

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

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

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

这个对象就像一个“模型”,只是没有setter。这这样代码的不同部分就不能改变状态#36825;造成难以复制的bug。

要更改状态中的某些内容,您需要调度一个操作。一个action是一个简单的JavaScript对象(注意我们没有引入任何魔法?)描述发生了什么。以下是一些示例操作:

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

强制每个更改都被描述为一个动作,让我们有一个清楚地了解应用程序中发生的事情。如果有什么改变了,我们知道它为什么改变。行动就像面包屑最后,为了把状态和动作联系在一起,我们写一个函数称为减速器。同样,它没有什么魔力-它只是一个函数,将状态和动作作为参数,并返回下一个应用程序的状态。很难为一个大应用程序,所以我们编写更小的函数来管理部分状态:

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;}}

我们编写另一个减速器来管理我们的完整状态通过调用这两个简化程序来获取相应的状态键:

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

这基本上是Redux的整个想法。请注意,我们还没有使用任何Redux API。它带有一些实用程序来促进这一点模式,但主要思想是你描述了你的状态随着时间的推移更新以响应操作对象,90%的代码你写的只是普通的JavaScript,没有使用Redux本身,它的API或任何魔法。

这是Redux over Flux的简单解释。Redux没有分派器。它依赖于称为简化器的纯函数。它不需要调度器。每个操作由一个或多个简化器处理以更新单个存储。由于数据是不可变的,因此简化器返回一个新的更新状态来更新存储输入图片描述

更多信息Flux vs Redux

我用Flux工作了很长时间,现在用Redux工作了很长时间。正如Dan指出的,两种架构并没有太大的不同。问题是Redux让事情变得更简单、更清晰。它在Flux之上教会了你一些事情。例如,Flux是单向数据流的完美例子。我们拥有数据的关注点分离,它的操作和视图层分离。在Redux中,我们有同样的事情,但我们也学习了不变性和纯函数。

从2018年年中从(几年)ExtJS迁移的新反应/Redux采用者:

在向下滑动redux学习曲线后,我有同样的问题,并认为纯通量会像OP一样简单。

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

在再次掌握锅炉板的同时,我尝试了一些其他状态管理库,我发现最好的是重赛

它比vanilla redux更直观,它减少了90%的样板文件,并减少了我在redux上花费的75%的时间(我认为图书馆应该做的事情),我能够立即获得几个企业应用程序。

它也使用相同的redux工具运行。这是一个好文章,涵盖了一些好处。

因此,对于任何来到这篇SO帖子搜索“更简单的Redux”的人,我建议尝试一下作为Redux的简单替代品,具有所有好处和1/4的样板。

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

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