因此,我一周前开始学习React,我不可避免地遇到了状态问题以及组件应该如何与应用程序的其余部分进行通信。我四处搜寻,Redux似乎是本月的风土人情。我通读了所有文档,并认为这实际上是一个非常革命性的想法。这是我的想法:
通常认为状态是非常邪恶的,并且是程序设计中大量错误的来源。Redux并未将所有内容分散在整个应用程序中,而是为什么不将其全部集中在必须发出动作才能更改的全局状态树中?听起来不错。所有程序都需要状态,因此让我们将其停留在一个不纯净的空间中,并仅在该空间内对其进行修改,以便轻松查找错误。然后,我们还可以声明性地将各个状态块绑定到React组件,并使它们自动重绘,并且一切都很好。
但是,我对整个设计有两个问题。首先,为什么状态树必须是不可变的?假设我不在乎时间旅行调试,热重装,并且已经在我的应用中实现了撤消/重做。要做这件事似乎很麻烦:
case COMPLETE_TODO: return [ ...state.slice(0, action.index), Object.assign({}, state[action.index], { completed: true }), ...state.slice(action.index + 1) ];
代替这个:
case COMPLETE_TODO: state[action.index].completed = true;
更不用说我正在做一个在线白板,只是为了学习,并且每个状态更改都可能像在命令列表中添加笔刷一样简单。一段时间后(数百个笔触),复制整个阵列可能开始变得非常昂贵和费时。
我可以接受一个全局状态树,该状态树与通过操作进行更改的UI无关,但是它真的需要不可变吗?像这样的简单实现有什么问题(草稿很粗。写在1分钟内)?
var store = { items: [] }; export function getState() { return store; } export function addTodo(text) { store.items.push({ "text": text, "completed", false}); } export function completeTodo(index) { store.items[index].completed = true; }
它仍然是通过发出的动作而变异的全局状态树,但是极其简单和有效。
Redux不只是美化了全球状态吗?
当然是的。但是,您曾经使用过的每个数据库都适用。最好将Redux视为内存数据库-您的组件可以依赖地依赖于该数据库。
不变性使检查子树是否被非常有效地更改变得容易,因为它简化了身份检查。
是的,您的实现是有效的,但是每次以某种方式操纵树时,都必须重新渲染整个虚拟dom。
如果您使用的是React,它将最终与实际dom进行对比,并执行最少的批优化操作,但是完整的自上而下的重新渲染仍然效率低下。
对于一棵不可变的树,无状态组件只需检查它所依赖的子树(一个或多个),与先前的值相比是否具有相同的标识,如果这样,则可以完全避免渲染。