我在尝试管理和访问不同组件和处理方法中的状态时,可以使用 RxJS 吗,而不是 Redux 或上下文?

136
我知道Redux是Flux的一个更好的“实现”,或者更准确地说,它是一个简化事物(应用状态管理)的重新设计。
我听说过很多关于响应式编程(RxJS)的东西,但我还没有深入学习它。
所以我的问题是:这两种技术之间有什么交集(共同点)吗?还是它们完全不同?它们是互补的吗?
Redux和Reach上下文API一起,是一种创建和管理状态存储的方式,可以通过Redux动作来观察。
RxJS是一种响应式编程语言,具有在不需要Redux动作和reducer的情况下设置和访问不同组件的状态的能力。
在管理和访问状态的目的上,相对于响应式编程范式,Redux作为状态存储可能更有用的地方在哪里?
在各个组件中管理和访问状态的目的上,你会如何决定使用其中之一而不是另一个?
5个回答

221

简而言之,它们是用于非常不同目的的非常不同的库,但是确实存在一些模糊的相似之处。

Redux 是一个用于管理应用程序中状态的工具。通常用作 UI 架构。将其视为(Angular 的一半)的替代品。

RxJS 是一种响应式编程库。通常用作在 JavaScript 中完成异步任务的工具。将其视为 Promise 的替代品。


响应式编程是一种范例(一种工作和思考方式),其中数据变化可以被“从远处观察到”。数据不会“从远处更改”。

这里有一个“从远处更改”的示例:

// In the controller.js file
model.set('name', 'George');

从控制器改变了模型

这是一个远距离观察的示例:

// logger.js
store.subscribe(function (data) {
    console.log(data);
});

在 Logger 中,我们观察 Store 中发生的数据变化(从远处),并将其写入控制台。


Redux 仅使用响应式编程范例:Store 是响应式的。你不会从远处设置它的内容。这就是为什么 Redux 中没有 store.set()。Store 从远处观察操作,并自行更改。而且 Store 允许他人从远处观察其数据。

RxJS 也使用响应式编程范例,但它不是一种架构,而是提供了基本的构建块,Observables,以实现这种“从远处观察”的模式。

总之,它们是为不同目的而设计的非常不同的东西,但它们共享一些思想。


6
不,你不应该同时使用它们。人们使用 Rx 模拟 Redux。快速搜索一下谷歌,就能为你找到示例。如果你想在响应式 UI 中使用 Rx,请查看 Andre 的框架 Cycle.js。最近我一直在使用它,感觉棒极了。API 最近有很多变化,但我相信他最终开始冻结其中的部分。 - Joel Dentici
23
根据官方 Redux 文档,“它们很好地协同工作。” - galki
16
他们一起工作得非常好!有一个Redux中间件可以让你使用RxJS和Observables来处理Redux actions。https://github.com/redux-observable/redux-observable 另外,我还写了一篇关于如何使用的博客文章:http://www.robinwieruch.de/redux-observable-rxjs/ - Robin Wieruch
1
Redux范式帮助我使我的Android项目代码库更具响应性。我们的数据流来自按钮和其他字段以更新状态,与RxJava一起使用,大大提高了可读性和性能。这些库确实很搭配,并且它们的好处是与语言无关的。 - Kenny Worden
3
它们一起工作效果非常好,但在实践中,响应式编程可以为您完成Redux的工作-将组件的状态与模型同步,因此通常没有必要同时使用两者。 - Filip Sobczak
1
人们一直说它们是非常不同的东西,这并不是真的。就给应用程序的不同组件提供数据的方式而言,它们非常相似。实际上,区别在于被观察或“使用”之前的存储方式。这是来自 Redux 页面本身的引用,它是上面评论的第二部分。问题是:如果你已经使用了 Rx,你真的需要 Redux 吗?也许不需要。在 Rx 中重新实现 Redux 并不难。有人说可以使用 Rx 的 .scan() 方法完成这个两行代码的任务。这完全有可能! - Christian Matthew

48

它们是非常不同的东西。

RxJS可用于进行响应式编程,是一个非常全面的库,拥有250多个操作符。

而Redux如Github存储库中所述,“Redux是JavaScript应用程序的可预测状态容器”。

Redux只是处理应用程序状态的工具。但相比之下,您可以只使用RxJS构建完整的应用程序。

希望这可以帮助:


3
你的回答也很好,@cmdv。我在写我的时候没有看到它。 - André Staltz
Rxjs能够与React Native一起使用吗? - mercury

9

Redux 是一个状态管理库,它带有明确定义的标准来进行更新操作。只要你遵循这些标准,你就可以保持数据流的健全和易于推理。它还提供了通过中间件和存储增强器来增强数据流的能力。

RxJS 是一种反应式编程工具包。你实际上可以将应用中发生的所有事情都视为流。RxJS 提供了非常丰富的工具集来管理这些流。

RxJS 和 Redux 有何交集?在 Redux 中,你使用操作来更新你的状态,显然这些操作可以被视为流。使用像 redux-observable 这样的中间件(不是必须的),你可以以一种反应式的方式实现所谓的“业务逻辑”。另外,你还可以从你的 Redux 存储中创建一个可观察对象,有时这可能比使用增强器更容易。


4
简而言之:
Redux:受Flux启发的库,用于状态管理。
RxJS:基于反应式编程思想的另一个JavaScript库,用于处理“流”(Observables等)。[阅读有关反应式编程的文章以了解流概念]。

1

我只是想补充一些实际差异,当我做Redux-inspired RxJS代码时。

我将每个操作类型映射到一个Subject实例。 每个有状态的组件都将具有一个Subject,然后将其映射到一个reducer函数中。 所有的reducer流都与merge结合,然后scan输出状态。 默认值在scan之前使用startWith设置。我对状态使用了publishReplay(1),但以后可能会删除它。

React纯渲染函数将是你通过发送所有生产者/Subjects来生成事件数据的唯一位置。

如果您有子组件,则需要描述这些状态如何组合成您的状态。 combineLatest可能是一个好的起点。

实现中的显着差异:

  • 没有中间件,只有rxjs操作符。我认为这是最大的优势和劣势。你仍然可以借鉴概念,但我发现很难从像redux和cycle.js这样的姊妹社区获得帮助,因为它是另一个定制解决方案。这就是为什么在这篇文章中我需要写“我”而不是“我们”的原因。

  • 没有switch/case或字符串用于操作类型。您有一种更动态的分离操作的方法。

  • rxjs可以用作其他工具,并且不仅限于状态管理。

  • 生产者数量比操作类型少吗?(我不确定)但是您可以在父组件中拥有许多对子组件进行监听的反应。这意味着较少的命令式代码和较少的复杂性。

  • 你拥有解决方案。不需要框架。好与坏。你最终会编写自己的框架。

  • 它更加分形,您可以轻松订阅来自子树或应用程序状态树多个部分的更改。

    • 猜猜如何像redux-obseravble那样做epics?非常容易。

我也在致力于更大的好处,其中子组件被描述为流。这意味着我们不必在reducers中混合父级和子级状态,因为我们可以基于组件结构递归地组合状态。

我还考虑跳过React,转而使用snabbdom或其他东西,直到React更好地处理反应状态。为什么我们要向上构建状态,然后再通过props打破它呢?所以我将尝试使用Snabbdom制作第二个版本的此模式。

这是一个更高级但小型的片段,其中state.ts文件构建状态流。这是ajax-form组件的状态,它获取具有验证规则和css样式的字段(输入)对象。在此文件中,我们只使用字段名称(对象键)将所有子项的状态组合成表单状态。

export default function create({
  Observable,
  ajaxInputs
}) {
  const fieldStreams = Object.keys(ajaxInputs)
  .map(function onMap(fieldName) {
    return ajaxInputs[fieldName].state.stream
    .map(function onMap(stateData) {
      return {stateData, fieldName}
    })
  })

  const stateStream = Observable.combineLatest(...fieldStreams)
  .map(function onMap(fieldStreamDataArray) {
    return fieldStreamDataArray.reduce(function onReduce(acc, fieldStreamData) {
    acc[fieldStreamData.fieldName] = fieldStreamData.stateData
    return acc
  }, {})
  })

  return {
    stream: stateStream
  }
}

虽然孤立的代码可能不会有太多含义,但它展示了如何向上构建状态,并轻松生成动态事件。付出的代价是需要理解一种不同风格的代码。而我喜欢为此付出代价。

一年过去了,我刚刚发现了你的答案,认为它仍然有效!我做了类似的事情,并同意你所有的观点。但是还有一个问题:你今天是否仍然持有相同的看法,或者你已经转变了? - Xceno
1
我需要修改对Redux中switch/case和action类型的批评。 我仍然以相同的方式编写代码,但尝试着让它在服务器端运行。 当涉及到React代码时,我已经成功地创建了一个小工具,帮助创建reducers/updaters。所以我仍然在做同样的事情,但更加精细。 最大的变化是我让每个叶节点在componentDidMount上订阅流,并在componentDidUnmount上取消订阅。 我还想在前端和后端都能够使用的响应式服务层。正在取得进展。 - Marcus Rådell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接