首页 > 解决方案 > Redux 减速器参考

问题描述

当我们触发一个动作时,redux 的状态会发生什么?

  1. 我们有 redux 的当前状态
  2. 我们称之为行动
  3. 每个 reducer 在包含正确 actionType 的 switch 中查找自己的 case
  4. 每个reducer都返回状态-即使在默认情况下,每个reducer是否都返回对状态的新引用return state

如果它在减速器中返回,状态实际上会发生什么?它使用某种reduce函数来比较状态并调用重新渲染,然后返回新的引用并做出反应,然后比较是否有任何变化并调用重新渲染?

标签: javascriptreduxreact-redux

解决方案


您在这里谈论的是一个减速器,它是通过将多个“切片”减速器组合而成的combineReducers。像这样的东西:

const rootReducer = combineReducers({
  users: usersReducer,
  posts: postsReducer,
})

假设我们dispatch是一个带有类型的动作ADD_USER——这是usersReducer会响应但不会响应的东西postsReducer

每个reducer都返回状态-即使在默认情况下,每个reducer是否都返回对状态的新引用return state

postsReducer不关心这个动作,只会return state. 这是对现有对象的引用。所以state.posts是相同的。

usersReducer为其状态创建并返回一个新对象。state.users对内存中与以前不同的对象的引用也是如此。如果其中嵌套了其他数组或对象那么state.user这些对象将是相同的引用,除非我们在 reducer 中替换它们。因此,您正在处理一个“浅拷贝”,其中state.users是一个新对象,但一个深度嵌套的对象state.users.byId[5]可能与以前完全相同。


你可能认为根在处理时总是一个新的对象引用,state因为combineReducers本质上是这样做的:

const rootReducer = (state, action) => ({
  users: usersReducer(state, action),
  posts: postsReducer(state, action),
});

实际实现更复杂,它涉及一些检查以防止不必要的对象创建。如果每个单独的 reducer 都只是使用default: return state;,则返回原始state对象。

以下是该combineReducers功能的工作原理:

  • 它有一个boolean标志属性hasChanged,最初是false.
  • 它创建 anextState最初是一个空对象(很明显这是一个新对象)。
  • 它遍历每个单独的属性 reducer,并nextState使用该属性的更新状态更新 。如果属性 reducer 返回一个新状态,则hasChanged变为true.
  • 如果在调用所有属性 reducer 之后hasChanged仍然是,则它忽略并返回原始变量。falsenextStatestate
  • 否则它返回nextState.

当使用类似的 React 绑定时useSelector,它(默认情况下)对返回的值进行严格的相等检查。因此,如果您返回一个新对象,它是前一个对象的精确副本,它将触发重新渲染,因为该对象是不同的引用。reselect这就是为什么如果涉及到通过array.map,等创建对象时,使用诸如记忆选择器之类的东西很重要array.filter。否则每次都会有一个新的对象引用。 useSelector还支持自定义相等检查,以便您可以控制何时发生重新渲染。


推荐阅读