根据redux的文档,reduce总是提供新的状态副本。 在连接的组件中,react-redux对mapStateToProps。中提到的属性进行了较浅的比较。 我的困惑是,由于redux总是提供新的状态副本,因此react-redux进行的浅表比较应始终为false,并且组件应始终重新呈现,但这不会发生。 有人可以解释我所缺少的吗?
我正在考虑在mapStateToProp中读取的所有属性都是对象。
答案 0 :(得分:0)
我们都同意mapStateToProps
如果存储状态相同则不会运行。因此,redux文档是:
connect生成的包装器组件订阅Redux 商店。每次调度动作时,它都会调用
store.getState()
并检查是否为lastState === currentState
。如果两种状态 值通过引用相同,那么它将不会重新运行您的mapStateToProps
函数,因为它假定其余的 存储状态也没有改变。
答案 Why isn't my component re-rendering, or my mapStateToProps running?可以描述您的情况,因为您可能会不小心直接改变状态。
由于您使用的是'combineReducers'(虽然很棒),所以还有一个“ Gotcha”:
combineReducers
实用程序功能尝试优化状态更新。如果 切片缩减器均未返回新值,然后CombineReducers 返回旧的状态对象,而不是新的对象。这意味着 异径管中的突变会导致根状态对象不存在 已更新,因此用户界面不会重新呈现。
答案 1 :(得分:0)
只要不对sub reducer进行突变,无论根状态是否为新对象,sub reducer都将保持引用不变,因此,在reducer的那部分进行connect的浅表比较始终返回true。因此,依赖于特定状态的组件不会发生任何重新渲染。
const subReducerState = { innerProp: 3 };
const prevRootState = { subReducerState: subReducerState };
const nextRootState = { subReducerState: subReducerState };
prevRootState.subReducerState === nextRootState.subReducerState // returns true
答案 2 :(得分:0)
Redux不会始终为您提供新副本。程序员应注意以下几点,以确保它在真正应有的时间工作:
- 使用
Object.assign()
或_.extend()
之类的功能复制对象, 以及诸如slice()
和concat()
之类的数组函数。- ES6中的数组扩展运算符,以及类似的对象扩展运算符 建议用于JavaScript的未来版本。
- 将不变的更新逻辑包装到更简单函数中的实用程序库
类似地,如果您使用的是combineReducer()
,请确保组成组合化合器的所有化合器实际上都在返回一个新对象。
您是否对旧状态进行了任何突变?如果这样做,那么这些操作将不会导致自己返回新对象。您需要返回 NEW 对象需要的更改,如上所述。切勿更改旧状态,因为以后会与新状态进行比较。
如果您有嵌套对象(例如main.subpart.nanopart
),并且您在化简版中的嵌套对象中进行了更改,则需要为其返回新对象 AND 为全部的父母。例如:nanopart
中的任何更改都应为nanopart
,subpart
和main
中的每一个返回新对象。 See here for a visual describing it
如果您的化简为未处理的操作返回旧状态(通常是这种情况),则您可能无法正确处理化简中的操作并导致从default
返回旧对象分支处理未处理的操作。
减速器应该是纯色的:给定输入,输出应相同(确定性纯计算)。因此,您不应使用诸如Date.now()
,Math.random()
之类的不确定元素。同样,您也不应引起副作用,例如API调用或路由传输。使减速器仅对旧状态进行纯计算,以将新状态作为新对象返回。在此处阅读basics of reducers
React-Redux也可能是导致问题的原因
用connect()
装饰的视图称为shouldComponentUpdate
,而该视图仅考虑更改的支撑。如果您的视图依赖于全局状态或其父组件(see React context),则您的组件将不会基于全局状态或父组件的更改而重新呈现。这可能是由您的第三方库引起的。您需要通过道具传递更改,或者指示您的组件不是纯正的(不建议您使用,因为它变得越来越慢)。
导出默认连接( mapStateToProps, 空值, 空值, { 纯:假 } )(您的App)
还要确保
您可以将动作创建者与
mapDispatchToProps
绑定connect()
或bindActionCreators()
方法的参数,或者 您手动致电dispatch()
。只是打电话给你MyActionCreators.addTodo()
函数将不起作用,因为它只是返回 动作,但不分派
查看这些疑难解答页面,其中详细介绍了这些内容: