浅层属性比较如何对连接的组件起作用?

时间:2019-05-19 07:47:40

标签: reactjs redux react-redux

根据redux的文档,reduce总是提供新的状态副本。 在连接的组件中,react-redux对mapStateToProps。中提到的属性进行了较浅的比较。 我的困惑是,由于redux总是提供新的状态副本,因此react-redux进行的浅表比较应始终为false,并且组件应始终重新呈现,但这不会发生。 有人可以解释我所缺少的吗?

我正在考虑在mapStateToProp中读取的所有属性都是对象。

3 个答案:

答案 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不会始终为您提供新副本。程序员应注意以下几点,以确保它在真正应有的时间工作:

  • 减速器是否真的在更改任何状态,并且不变地返回一个新对象(见下文)?如果不是,您的redux reducer将仅返回旧对象,因此无需重新渲染。您可能会错误地返回原始数组。
  • 使用Object.assign()_.extend()之类的功能复制对象, 以及诸如slice()concat()之类的数组函数。
  • ES6中的数组扩展运算符,以及类似的对象扩展运算符 建议用于JavaScript的未来版本。
  • 将不变的更新逻辑包装到更简单函数中的实用程序库
  • 类似地,如果您使用的是combineReducer(),请确保组成组合化合器的所有化合器实际上都在返回一个新对象。

  • 您是否对旧状态进行了任何突变?如果这样做,那么这些操作将不会导致自己返回新对象。您需要返回 NEW 对象需要的更改,如上所述。切勿更改旧状态,因为以后会与新状态进行比较。

  • 如果您有嵌套对象(例如main.subpart.nanopart),并且您在化简版中的嵌套对象中进行了更改,则需要为其返回新对象 AND 全部的父母。例如:nanopart中的任何更改都应为nanopartsubpartmain中的每一个返回新对象。 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()函数将不起作用,因为它只是返回 动作,但不分派

查看这些疑难解答页面,其中详细介绍了这些内容:

https://redux.js.org/troubleshooting

https://redux.js.org/faq/react-redux#why-isn-t-my-component-re-rendering-or-my-mapstatetoprops-running

https://react-redux.js.org/troubleshooting