1124
4

8 回答 8

1954

Redux 作者在这里!

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

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

减速机组成

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

另一方面,由于 reducer 的组合,Redux 的分页是很自然的。它一直是减速器,所以你可以编写一个减速器工厂来生成分页减速器,然后在你的减速器树中使用它。之所以这么简单,关键是因为在 Flux 中,store 是扁平的,但在 Redux 中,reducer 可以通过函数组合进行嵌套,就像 React 组件可以嵌套一样。

这种模式还启用了诸如无用户代码撤消/重做之类的精彩功能。你能想象将 Undo/Redo 插入 Flux 应用程序是两行代码吗?几乎不。使用 Redux,再次感谢 reducer 组合模式。我需要强调它并没有什么新东西——这是Elm Architecture中开创并详细描述的模式,它本身就受到 Flux 的影响。

服务器渲染

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

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

在 Flux 中仍然需要解决以下问题(您可以自己解决,也可以借助FlummoxAlt等您喜欢的 Flux 库):

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

诚然 Flux 框架(不是 vanilla Flux)可以解决这些问题,但我发现它们过于复杂。例如,Flummox 要求您在您的商店中实施serialize()deserialize()。Alt 通过提供takeSnapshot()在 JSON 树中自动序列化您的状态来更好地解决这个问题。

Redux 更进一步:因为只有一个 store(由许多 reducer 管理),所以您不需要任何特殊的 API 来管理(重新)水化。您不需要“刷新”或“水合”存储——只有一个存储,您可以读取其当前状态,或创建具有新状态的新存储。每个请求都会获得一个单独的商店实例。阅读有关使用 Redux 进行服务器渲染的更多信息。

同样,这在 Flux 和 Redux 中都是可能的,但是 Flux 库通过引入大量 API 和约定来解决这个问题,而 Redux 甚至不必解决它,因为它在由于概念简单,因此排名第一。

开发者体验

我实际上并没有打算让 Redux 成为一个流行的 Flux 库——我是在我的ReactEurope 演讲中写的,关于时间旅行的热重载。我有一个主要目标:可以通过删除操作来动态更改 reducer 代码,甚至“改变过去”,并查看重新计算的状态。

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

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

生态系统

Redux 拥有丰富且快速发展的生态系统。这是因为它提供了一些扩展点,例如中间件。它的设计考虑了诸如日志记录、对PromisesObservables路由不变性开发检查持久性等用例的支持。并非所有这些都会变得有用,但很高兴能够访问一组可以轻松组合以协同工作的工具。

简单

Redux 保留了 Flux 的所有优点(动作的记录和重放、单向数据流、依赖突变),并在不引入 Dispatcher 和存储注册的情况下增加了新的优点(易于撤消重做、热重载)。

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

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

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


另请参阅我对使用 Redux 与 Flux 相比的缺点的回答

于 2015-10-03T08:26:25.950 回答
101

在 Quora,有人说

首先,完全可以使用 React 编写应用程序而无需 Flux。

此外,我创建的这个可视化图表可以快速查看两者,对于不想阅读整个解释的人来说可能是一个快速的答案: Flux 与 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'
}

这个对象就像一个“模型”,只是没有设置器。这是为了让代码的不同部分不能随意改变状态,导致难以重现的错误。

要更改状态中的某些内容,您需要调度一个操作。动作是一个简单的 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 或任何魔法。

于 2017-03-22T12:59:53.423 回答
57

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

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

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

于 2015-09-23T14:51:33.203 回答
27

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

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

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

我们决定继续前进,我们将迁移到 Redux,我建议您也这样做;)

于 2016-01-05T13:45:53.747 回答
20

这里是 Redux over Flux 的简单解释。Redux 没有调度程序。它依赖于称为 reducer 的纯函数。它不需要调度程序。每个操作都由一个或多个减速器处理以更新单个存储。由于数据是不可变的,reducers 返回一个新的更新状态来更新存储在此处输入图像描述

欲了解更多信息通量与 Redux

于 2017-04-18T14:27:02.457 回答
6

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

于 2018-01-25T12:26:44.820 回答
5

来自 2018 年中期从(几年的)ExtJS 迁移的新的 react/redux 采用者:

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

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

在再次掌握样板时,我尝试了一些其他状态管理库,我发现最好的是rematch

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

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

因此,对于到达此 SO 帖子搜索“更简单的 redux”的其他人,我建议尝试将其作为 redux 的简单替代品,具有所有优点和 1/4 样板。

于 2018-11-19T19:44:45.277 回答
0

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

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

于 2019-04-11T13:10:33.803 回答