Redux不只是美化了全球状态吗?


84

所以我一周前开始学习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;
}

它仍然是通过发出的动作而变异的全局状态树,但是极其简单和有效。


2
“其中之一,为什么状态树需要是不变的?” ---那么您必须提供一种算法来确定数据是否已更改。对于任意数据结构(如果它是可变的),不可能实现它。采取immutablejs并使用return state.setIn([action.index, 'completed'], true);以减少样板。
zerkms 2015年

1
PS:return state.map(i => i.index == action.index ? {...i, completed: true} : i);
zerkms,2015年

Answers:


52

Redux不只是美化了全球状态吗?

当然如此。但是,您曾经使用过的每个数据库都适用。最好将Redux视为内存数据库-您的组件可以依赖地依赖于该数据库。

不变性使检查子树是否被非常有效地更改变得容易,因为它简化了身份检查。

是的,您的实现是有效的,但是每次以某种方式操纵树时,都必须重新渲染整个虚拟dom。

如果您使用的是React,它将最终与实际的dom进行对比,并执行最少的批优化操作,但是完整的自上而下的重新渲染仍然效率低下。

对于一棵不可变的树,无状态组件只需检查它所依赖的子树,与先前值相比的身份是否不同,如果这样,则可以完全避免渲染。


3
这不是过早的优化吗?另外,我们怎么知道不断复制不可变对象的成本要比重新渲染DOM少(React的Virtual DOM不会大大减轻这一成本吗?)
Ryan Peschel 2015年

3
好吧,GUI库很长时间以来一直在进行这种优化(请参阅:bitquabit.com/post/the-more-things-change)另外,对不可变数据结构的管理并不像您想象的那样昂贵(例如,如果一个节点更改后,只有一个父链需要链接-其余节点不受影响。因此,我们不会为每个操作都复制整个数据结构-我们重用了尚未更改的子组件来构建新的数据结构。
lorefnon

4
此外,Reacts Virtual DOM并不是完全黑暗的魔术-从React docs引用:“生成最小数量的操作以将一棵树转换为另一棵树是一个复杂且经过充分研究的问题-现有技术算法的复杂程度依次的O(n3),其中n是树中的节点数。”
lorefnon

2
在实践中,React能够表现得更好的原因是:React依赖于启发式算法-因此:“如果您不提供稳定的键(例如,使用Math.random()),则所有子树都将每次都可以重新渲染。通过为用户提供选择密钥的选择,他们可以自行射击。” 因此,就像您可以通过提供稳定的键来帮助React一样,您可以通过提供不可变的数据道具来帮助React。
lorefnon

1
关于笔触数组-请参考:facebook.github.io/immutable-js/docs/# /List从文档引用:列表是有序索引的密集集合,很像JavaScript数组。列表实现了Deque,并有效地从末尾(推动,弹出)和开始(未移位,移位)进行添加和删除。
lorefnon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.