用于文本编辑器的Redux架构:处理耦合状态

时间:2017-04-25 01:24:51

标签: javascript redux

我正在使用React / Redux构建一个应用程序,它在某些方面类似于文本编辑器。它不完全是文本编辑器,但它是相同的一般范例。有一个用于放置新项目的光标。可以添加,选择,删除项目等。

我正在以一种符合redux精神的方式努力构建减速器的最佳方法。我有单独的状态切片,表示选择状态,文本本身,光标状态和其他设置。我认为" redux"方法是为每个状态切片设置减速器,独立地改变状态以响应动作。

然而,在文本编辑器中,这些状态切片比初看起来更加耦合。按键时,有时会在光标位置添加一个字母,光标将向前移动。但是,如果选择了文本,则将首先删除所选文本。如果你在"插入"模式,右边的文字将被消费"。或者修改键可能已关闭,文本根本没有添加。

换句话说,不同的状态切片是非常耦合的,并且在一个切片中发生的事情取决于其他状态切片的当前状态。

我已经阅读"Beyond Combine Reducers" section in the Redux manual并知道如何在切片缩减器之间共享状态,但如果最终结果将整个状态传递给每个切片缩减器,这似乎是不优雅的。我不喜欢他的方法的另一件事是,每个减速器必须查看整体状态,并独立地得出关于它对特定动作的正确响应应该是什么的相同结论。这就是我应该做的事情,或者我应该以某种方式构建我的状态?

一个集中式缩减器的替代方案告诉光标,选择状态,内容等,如何变异在概念上更容易,但似乎不能很好地扩展。

I've also read that many times coupled state is a sign that your state isn't minimal并且你应该重组并使用memoized选择器。然而,这似乎并非如此。光标的位置不能从文本中导出,也不是选择状态。

最后,我还考虑过Thunk中间件,因为我已经看到这是处理多个/更复杂操作的建议。我犹豫不决,因为它似乎更适合异步调度,而事实并非如此。

我想了解设计此类应用程序的正确方法,该方法最符合" redux"设计模式,并了解如果有多种方法可能会有任何权衡。

2 个答案:

答案 0 :(得分:5)

我写了"Structuring Reducers" doc部分,很高兴看到人们至少阅读它并发现它很有用:)

你是对的,Redux reducer逻辑的惯用方法是小型reducer函数,由状态片组织,独立响应相同的动作。但是,这不是一个固定的要求,并且有时候将某些逻辑合并到一个地方更有意义。

在没有看到你的状态结构是什么以及确切地想要解决什么问题的情况下给出绝对的具体建议有点困难,但总的来说,你应该随意以任何方式构建你的状态和你的减速器逻辑。最适合你的应用程序。如果在更集中的reducer函数中更好地使用某些逻辑来同时更新几个嵌套的状态,那就去吧!

作为其他一些观察结果:

根据Redux FAQ question on "sharing state across reducers",一种方法是将更多信息放入调度的操作中。例如,您可以发送{type : "KEYSTROKE", key : "A"},而不是发送{type : "KEYSTROKE", key : "A", cursorPos : 12345, ctrl : true, alt : false}

此外,虽然thunks是基本异步逻辑的好地方,但它们对复杂的同步逻辑也很有用,包括检查当前的app状态。我有a gist that demonstrates some common thunk use cases

Lemme抛出了一些可能对您提供一般帮助的资源:

(作为旁注,我目前正在撰写博客文章,讨论Redux需要的实际技术限制以及为什么,以及您“打算”使用Redux的方式,vs如何可能使用Redux。请花一点时间来完成它,但如果你有兴趣,请留意我的博客。)

最后,如果您想进一步讨论事情,Discord上的Reactiflux聊天频道是一个闲逛,提问和学习的好地方。邀请链接位于https://www.reactiflux.com。请随意到那儿去问问题 - 我通常在美国时间晚上去那里,但是总会有很多人高兴地讨论事情。

答案 1 :(得分:0)

似乎你正在承担一项艰巨的任务;可能你已经知道了,但是从头开始创建文本编辑器并不是一件容易的事。

您是否使用现有软件进行了评估?

最近,我成功地使用了超级强大的Codemirror并将其与React.js应用程序集成。 Codemirror已经很好地管理了文档状态的概念。

这意味着:

  • Codemirror实例完全管理编辑器(AKA:文档)
  • 通过回调和事件将React环境附加到文档。

如果Codemirror不符合您的需求,请查看它的代码和internals说明。