我的应用程序和商店
使用Redux和ReactJS,我在存储中保留一个对象数组(称为结果),并调度对它进行排序和操作的操作 . 在mapStateToProps中,我返回此结果数组,该结果数组在视图的列表中呈现结果 .
// in Component file
export default class ResultList extends Component {
constructor(props) {
super(props);
this.renderResults = this.renderResults.bind(this);
}
renderResults(results) {
return (
results.map((result) => {
return <AnotherComponent />
})
);
}
render() {
const { results } = this.props;
return (
<div>
<ul>
{this.renderResults(results)}
</ul>
</div>
)
// in Container Component file
const mapStateToProps = (state, ownProps) => {
console.log('map state is triggered');
return {
results: state.results
};
}
问题
我发现虽然我的mapStateToProps成功触发将道具更新到我的类组件,但出于某种原因 the view only updates on the FIRST time that the results array gets manipulated, but does not update on future updates to the store. (请参阅下面的更新 . 这不完全准确 . )
我已经确定这个问题不是因为我的减速器中的状态发生了变化,这种情况经常发生;我已经确认每次商店更新时都会运行mapStateToProps(如console.log所示) . 问题似乎是从mapStateToProps返回的结果道具和实际呈现结果数组的视图之间的问题,但是我没有看到Redux在幕后做什么的可见性 .
其他人对我所遇到的最接近的问题似乎就是这个,但我不知道这个修复如何或者是否适用于我对存储数组的使用:https://forums.meteor.com/t/the-state-is-correctly-mutated-and-returned-but-view-does-not-rerender/28840/5
任何帮助将不胜感激 . 谢谢 .
更新
我道歉,但必须纠正我上面的陈述,说明在第一次商店中的结果更新后,视图没有进一步的更新 . 通过进一步的测试,我发现这并不完全正确 . The view gets updated only when the results array is sorted according to case 1 of the below sorting function. Cases 2 and 3 are the ones that result in no update to the view. 这可能是/可能不是必要的信息,但结果数组按一个循环中的这3种情况按以下顺序排序:案例1,案例3,案例2 .
// in reducer index.js file
case SORT_RESULTS:
return {
...state,
results: sortArr(state.results, state.sortType)
};
// sorting function
function sortArr(arr, sortType) {
let newArr = [];
switch (sortType) {
case '1':
for (let i = arr.length - 1; i >= 0; i--) {
newArr.push(arr[i]);
}
return newArr;
case '2':
newArr = arr;
newArr.sort((a, b) => {
return b.num - a.num;
});
return newArr;
case '3':
newArr = arr;
newArr.sort((a, b) => {
let id1 = a.id.toLowerCase();
let id2 = b.id.toLowerCase();
if (id1 < id2) {
return -1;
}
if (id1 > id2) {
return 1;
}
return 0;
});
return newArr;
default:
return arr;
}
}
1 回答
解决方案
这是罪魁祸首:
newArr = arr
. 将其更改为newArr = arr.slice()
,视图将在每种排序中更新 .可能的根本原因
至于为什么这个解决方案有效,我邀请其他人的观点 . 这是我的想法:
根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice:
使用
newArr = arr
复制结果数组似乎只复制指针(到数组),这实际上只是内存中的引用 . 如果这个陈述是真的,那么Redux根本不会认为状态已被改变,因为它正在比较完全相同的指针(state.results),即使确认数组本身的实际数据通过排序改变 . 通过slice()
复制一个全新的数组将涉及一个新的指针和数据,这将被检测为更改为引擎盖下的Redux .