React Redux:即使 mapStateToProps 是,视图也没有更新
Posted
技术标签:
【中文标题】React Redux:即使 mapStateToProps 是,视图也没有更新【英文标题】:React Redux: View not getting updated even though mapStateToProps is 【发布时间】:2017-12-01 02:46:16 【问题描述】:我的应用程序和商店
将 Redux 与 ReactJS 结合使用,我在 store 中保存了一个对象数组(称为结果)并调度对它进行排序和操作的操作。在 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 成功触发更新道具到我的类组件,出于某种原因视图仅在结果数组被操纵的第一次更新,但是不会更新商店的未来更新。 (请参阅下面的更新。这并不完全准确。)
我已经确定这个问题不是由于我的减速器中的变异状态(通常情况下);我已确认每次更新商店时都会运行 mapStateToProps(如 console.log 所示)。问题似乎在于从 mapStateToProps 返回的结果道具和实际呈现结果数组的视图之间,但我无法看到 Redux 在幕后所做的事情。
其他人遇到的最接近我遇到的问题似乎是这个,但我不知道此修复如何或是否适用于我对存储数组的使用:https://forums.meteor.com/t/the-state-is-correctly-mutated-and-returned-but-view-does-not-rerender/28840/5
任何帮助将不胜感激。谢谢。
更新
我很抱歉,但必须更正我上面的声明,即在商店中的结果第一次更新后视图没有进一步的更新。通过进一步的测试,我发现这并不完全正确。 仅当根据以下排序函数的案例 1 对结果数组进行排序时,视图才会更新。情况 2 和 3 是导致视图不更新的情况。 这可能是/可能不是必要的信息,但结果数组在 onClick 循环中按以下顺序按这 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;
【问题讨论】:
您尝试在mapStateToProps
中记录state.results
吗?
是的,我使用 redux-logger 中的 createLogger() 记录每次调度的状态。结果数组得到正确操作/更新。在 mapStateToProps 中执行 console.log(state.results) 会产生相同的结果。
你能退出componentWillRecieveProps(nextProps) console.log(nextProps.results)
看看那里的道具有没有更新吗?
componentWillReceiveProps 也只在结果存储的第一次更新时运行
我已经用澄清信息更新了帖子。我确信问题更多在于我对结果数组进行排序或返回新状态的方式。
【参考方案1】:
解决方案
这是罪魁祸首:newArr = arr
。将其更改为newArr = arr.slice()
,视图将在每次排序时更新。
可能的根本原因
至于为什么这个解决方案有效,我邀请其他人的观点。以下是我的想法:
根据https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Array/slice:
“slice() 方法将数组的一部分的浅拷贝返回到从开始到结束(不包括结束)选择的新数组对象中。”
使用newArr = arr
复制结果数组似乎只是复制了指针(指向数组),实际上只是内存中的一个引用。如果这个说法是真的,那么Redux不会考虑状态完全改变了,因为它正在比较完全相同的指针(state.results),即使数组本身的实际数据已通过排序确认更改。通过slice()
复制一个全新的数组将涉及一个新的指针和数据,这将被检测为对 Redux 的底层更改。
【讨论】:
完全有同样的问题,让我发疯。感谢您的发帖! 是的。现在使用 lodash _.cloneDeep 没有问题 我在同样的问题上抛出了一个扩展运算符。感觉丑陋且效率低下,但它确实有效。以上是关于React Redux:即使 mapStateToProps 是,视图也没有更新的主要内容,如果未能解决你的问题,请参考以下文章
React-Redux 应用程序真的可以像 Backbone 一样扩展吗?即使重新选择。在移动
找不到 react-redux 上下文值;请确保组件包含在 <Provider> 中,即使它已经包含在提供者中
react-redux 类型文件中的 TypeScript 错误