Redux的mapStateToProps如何触发React组件更新

时间:2016-05-09 19:50:48

标签: reactjs redux react-redux

在我的react / redux项目中,我有一个对数组进行排序的操作:



case 'SORT_BY_NAME':  
  var newList = state.list; //.slice() 
  newList.sort(function(a,b){
    if (a.name > b.name){
      return 1;
    } else if (a.name < b.name){
      return -1;
    } else {
      return 0;
    }
  });    
  return Object.assign({}, state, { list: newList } );
&#13;
&#13;
&#13; 该操作根据所需字段成功对数组进行了排序, 状态对象的形状符合我的预期,并且在我的反应组件 mapStateToProps 被命中,并且在mapStateToProps中,状态值准确地反映了数组的排序状态。

初始渲染很好。但排序操作无法导致我的组件的渲染方法再次被调用,因此UI中的数据从未出现过排序。

我的项目架构类似于Redux文档中的Reddit example。但是,我也使用react-redux连接mapStateToProps。下面是我的组件设计的精简版本:

&#13;
&#13;
class MyComponent extends React.Component{
	render(){
		<ul> 
		    {list.map(item =>
		      <li key={item.id}> 
			        {item.name}  
		      </li>
		    )}
	  	</ul>  
	}
} 

function mapStateToProps(state){  
  return {
	list: state.list;
	}
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MyComponent)
&#13;
&#13;
&#13; 最终我意识到我的问题的简单解决方案是在使用slice()对其进行排序之前克隆列表。因此,我的问题不是如何解决问题,而是为什么发生了这个问题。问题是redux的mapStateToProps没有调用render()吗?或者反应组件没有看到新的状态对象?

通过在mapStateToProps中设置断点,看起来好像正确设置/更改了状态;根据Chrome调试器中的Redux devtools,该商店看起来应该如此。

我的项目太大,无法创建一个完全重现我的问题的演示小提琴。当我试图创建一个最小尺寸的小提琴来重现这个问题时,我更加困惑,因为当我不使用Redux的连接时不会出现这个问题。 Link to fiddle

总结一下,我的问题是为什么在使用mapStateToProps时排序没有生效。我最好的猜测是,如果我的排序操作改变了先前的状态,以便新状态与先前的状态匹配,那么就没有需要重新渲染的方差。也许mapStateToProps比较了先前和新状态,并且它没有将新道具与道具进行比较。 DOM中的表示。

1 个答案:

答案 0 :(得分:5)

React Redux connect()经过大量优化,并假设mapStateToProps是纯函数。

通过调用state.list.sort(),您正在改变Redux中不允许存储状态。通常,最好记住哪些方法正在变异,哪些方法不变。例如,splice()是突变但slice()不是; push()正在变异,但concat()不是。你永远不应该使用从商店获得的状态的变异方法。

您还可以查看https://github.com/leoasis/redux-immutable-state-invariant之类的内容,以便更轻松地检测这些案例,或使用https://facebook.github.io/immutable-js/https://github.com/rtfeldman/seamless-immutable来强制执行不变性。这是可选的,取决于您。