我正在使用ReactJS,并希望将过滤和排序的数组传递到组件的props中,如下面的代码片段所示:
<component arrayData={justAnArray
.filter(//some condition here)
.sort(//sorting function here)} />
该组件旨在在收到的道具与之前的道具不同时更新其状态,如下所示:
componentWillReceiveProps(nextProps){
if (this.props.arrayData != nextProps.arrayData){
this.setState({ // some state here })
}
}
这导致了错误
超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制嵌套更新的数量以防止无限循环。
在故障排除过程中,我发现如果仅使用 .sort() 传递组件不会导致任何错误,即
<component arrayData={justAnArray
.sort(//sorting function here)} />
但是如果只传递 .filter,则会出现错误,即
<component arrayData={justAnArray
.filter(//some condition here)/>
这很奇怪,所以我开始研究 Array.prototype.sort() 和 Array.prototype.filter() 之间的区别。我发现 .filter() 返回一个新数组,而 .sort() 似乎返回原始数组,因为排序已经就地完成。
这可能是导致错误的原因吗?如果是,我应该怎么做才能防止此错误?
谢谢。
编辑:根据Kalidindi的要求@Nandu,我正在发布相关代码:
class Pagination extends Component {
constructor(props) {
super(props);
this.state = {
pager: {}
};
}
componentWillMount() {
// set page if items array isn't empty
if (this.props.items && this.props.items.length) {
this.setPage(this.props.initialPage);
}
}
componentWillReceiveProps(nextProps) {
// reset page if items array has changed
if (this.props.items != nextProps.items) {
this.setPage(this.props.initialPage);
}
}
setPage(page) {
var items = this.props.items;
var pager = this.state.pager;
if (page < 1 || page > pager.totalPages) {
return;
}
// get new pager object for specified page
pager = this.getPager(items.length, page, 3);
// get new page of items from items array
var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1);
// update state
this.state.pager = pager;
// call change page function in parent component
this.props.onChangePage(pageOfItems);
}
render() {
return( //render )
}
}
export default Pagination;
这基本上是这个在线 ReactJS 分页示例的 React Native 版本。
这就是我使用该组件的方式:
const someData= [{id: 1, title: 'a'},
{id: 2, title: 'b'},
{id: 3, title: 'c'},
{id: 4, title: 'd'},
{id: 5, title: 'e'},];
class SomePage extends Component {
constructor(){
super();
this.state={
pageOfItems: [],
}
this.onChangePage = this.onChangePage.bind(this);
this.filterAndSort = this.filterAndSort.bind(this);
}
filterItems = (items) => {
return items.filter(this.handleFilter);
}
sortItems = (items) => {
return items.sort(this.handleSort);
}
filterAndSort = () =>{
return this.sortItems(this.filterItems(someData));
}
onChangePage = (pageOfItems) =>{
//update state with new page of alignItems
this.setState({ pageOfItems: pageOfItems });
}
render(){
return(
<ScrollView style={{flex: 1}}>
{this.state.pageOfItems
.map((item) => {
return(
<box item={item} />
//just a component that displays the objects inside the arrays
)
})
}
</ScrollView>
<Pagination items={this.filterAndSort()} onChangePage={this.onChangePage} />
)
}
export default SomePage;
编辑2:
仅供其他人参考,这个问题的答案不是像我那样直接使用 '===' 比较数组。欲了解更多信息,请参阅@Nandu Kalidindi的回答。
-
无需
setState
componentWillReceiveProps
,单纯的赋值就足够了。这不是无限循环的原因,而只是一种很好的做法。 -
永远不要比较这样的数组。
[1] == [1] is always false
.要么使用JSON.stringify
要么使用这种方法 如何在 JavaScript 中比较数组? -
现在,
filter
+sort
不起作用而不是仅sort
的原因是因为filter
创建了一个新数组,这意味着一个新的引用,其中sort
返回相同的引用
在此处查看差异。
k = [1, 2, 3, 4]
r = k.sort()
console.log(k === r)
//TRUE
r = k.filter(elem => true).sort()
console.log(k === r)
// FALSE
因此,当您使用filter
+sort
时,无论您输入的条件如何,您的组件都会不断设置状态,而sort
期间它始终相等,并且状态更新永远不会发生。
修改狙击手,如下所示
componentWillReceiveProps(nextProps){
if (JSON.stringify(this.props.arrayData) != JSON.stringify(nextProps.arrayData)){
this.state.arrayData = nextProps.arrayData;
}
}
现在,为什么你的组件无限地重新渲染是另一个谜,你必须在你的componentWillUpdate
或shouldComponentUpdate
钩子中设置状态。这只是我的猜测。这就是为什么我建议你发布那里的所有相关代码。