我对Redux和React有一个奇怪的问题。
状态发生了正确的变化,在mapStateToProps
中,我也得到了正确的新状态,但在映射之后,组件将不会重新渲染。
这样,组件不会重新渲染:
import React, { Component } from 'react';
import { connect } from 'react-redux';
class ListItem extends Component {
render() {
return (<li>{this.props.item.text}</li>);
}
}
const mapStateToProps = (state, ownProps) => {
return {
item: state.test.byID[ownProps.itemID]
};
}
export default connect(mapStateToProps)(ListItem);
但是,如果我拆分项目,那么组件会重新渲染:
import React, { Component } from 'react';
import { connect } from 'react-redux';
class ListItem extends Component {
render() {
return(<li>{this.props.text}</li>);
}
}
const mapStateToProps = (state, ownProps) => {
return {
id: state.test.byID[ownProps.itemID].id,
text: state.test.byID[ownProps.itemID].text
};
}
export default connect(mapStateToProps)(ListItem);
我不知道为什么。
减速机:
const startState = {
byID: {
'a1': {id: 'a1', text: 'test1'},
'a2': {id: 'a2', text: 'test2'},
'a3': {id: 'a3', text: 'test3'},
'a4': {id: 'a4', text: 'test4'},
'a5': {id: 'a5', text: 'test5'},
'a6': {id: 'a6', text: 'test6'},
'a7': {id: 'a7', text: 'test7'},
},
all: ['a1', 'a2','a3', 'a4', 'a5', 'a6', 'a7']
};
export default function reducer(state = startState, action) {
switch (action.type) {
case 'ADD_TEXT':
const newState = {...state};
newState.byID[action.id].text = action.text;
return newState
default:
return state;
}
}
有什么想法吗?
答案 0 :(得分:3)
假设您要更改text
个数组对象中的byID
字段。使用您的代码:
newState.byID[action.id].text = action.text;
您正在改变您的状态,因此React可能在识别更改时遇到问题,因为item
道具中对象的引用不会改变,只会改变它的属性。如果有浅检查,它就不会重新渲染,因为它“假设”对象根本不会改变。
在第二种情况下,您将返回prop text
这是字符串类型,因此不会像对象那样进行浅层检查,并且相等的比较===
将区分更改并正确地重新呈现组件
有关更多说明,您可能需要查看Immutability in React。
通过传播运营商保持不变性的想法:
const newState = {...state};
可以进行顶级引用,但不适用于嵌套子对象:
对象传播执行对象的浅表副本。仅克隆对象本身,而不克隆嵌套实例。 An easy guide to object rest/spread properties in JavaScript
虽然变异对象似乎是您提供的代码中最容易出错的部分,但Component
React类可以深入调查对象更改(PureComponent
没有)和问题可能与另一个问题有关。