【问题标题】:Isn't Redux just glorified global state?Redux 不只是美化了全局状态吗?
【发布时间】:2016-01-30 04:20:09
【问题描述】:

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

它仍然是一个全局状态树,通过发出的动作进行变异,但非常简单和高效。

【问题讨论】:

  • “一方面,为什么状态树需要是不可变的?” --- 那么您必须提供一种算法来确定数据是否已更改。不可能为任意数据结构(如果它是可变的)实现它。取immutablejs 并使用return state.setIn([action.index, 'completed'], true); 来减少样板。
  • PS:return state.map(i => i.index == action.index ? {...i, completed: true} : i);

标签: javascript reactjs state immutability redux


【解决方案1】:

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

当然是。但同样适用于您曾经使用过的每个数据库。最好将 Redux 视为内存数据库 - 您的组件可以被动地依赖它。

不变性使检查任何子树是否已被更改非常有效,因为它简化了身份检查。

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

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

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

【讨论】:

  • 这不是有点过早的优化吗?另外,我们怎么知道不断复制不可变对象的成本低于重新渲染 DOM(React 的虚拟 DOM 也不会大大降低这个成本?)
  • 好吧,GUI 库这种优化已经很长时间了(参考:bitquabit.com/post/the-more-things-change)另外,不可变数据结构的管理并不像您想象的那么昂贵——例如,如果一个节点被更改,只有一条父链需要链接 - 其余节点不受影响。所以我们不会为每个动作复制整个数据结构——我们重用没有改变的子组件来构建一个新的数据结构。
  • Also Reacts Virtual DOM 并不是什么黑魔法——引用 React 文档:“生成将一棵树转换为另一棵树的最少操作数是一个复杂且经过充分研究的问题——艺术算法的复杂度约为 O(n3),其中 n 是树中的节点数。"
  • React 在实践中能够表现得更好的原因是:React 依赖于启发式 - 所以:“如果你不提供稳定的密钥(例如使用 Math.random()),所有的子树每次都会重新渲染。通过让用户选择键,他们有能力在脚下开枪。”所以就像你可以通过提供稳定的键来帮助 React,同样你可以通过提供不可变的数据道具来帮助 React。
  • 关于你的笔触数组——请参考:facebook.github.io/immutable-js/docs/#/List 引用自文档:列表是有序索引密集集合,很像 JavaScript 数组。列表实现了 Deque,在末尾(push、pop)和开头(unshift、shift)都有效地添加和删除。
猜你喜欢
  • 2016-10-28
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2019-09-10
  • 2018-05-02
  • 2018-09-16
相关资源
最近更新 更多