我只是想补充一些实际差异,当我做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
}
}
虽然孤立的代码可能不会有太多含义,但它展示了如何向上构建状态,并轻松生成动态事件。付出的代价是需要理解一种不同风格的代码。而我喜欢为此付出代价。