我有一个简单的组件,该组件从对象数组构建报告列表,我试图添加过滤器和排序功能(在一定程度上确实起作用),排序功能有效,但我担心我尽管尝试将原始状态复制到新数组中,但仍在更改状态。
我的过滤器在第一时间工作,但是由于状态已突变,或者因为我无法过滤初始状态,因此它不会过滤其他结果?这使我困惑了几个小时,非常感谢您的帮助。
非常感谢
constructor(props) {
super(props);
this.state = {
reports: props.data
};
this.handleSortBy = this.handleSortBy.bind(this);
this.handleFilterType = this.handleFilterType.bind(this);
}
handleSortBy(event) {
const copy = [...this.state.reports];
if (event.target.value === 'A-Z') {
return this.setState({
reports: copy.sort((a, b) => a.name.localeCompare(b.name))
});
}
if (event.target.value === 'Z-A') {
this.setState({
reports: copy
.sort((a, b) => a.name.localeCompare(b.name))
.reverse()
});
}
}
handleFilterType(event) {
this.setState({
reports: this.state.reports.filter(item => {
return item.type === event.target.value;
})
});
}
预先感谢:)
答案 0 :(得分:0)
我认为问题在于每次您进行过滤时,您都是从state.reports
中删除项目,而从未从props.data
中收回它们。
相反,每次进行过滤/排序时,您都应从state.reports
中重建props.data
。
或者,更好的IMO方法是将过滤/排序设置存储在state
中,并根据当前设置对props.data
中的render
进行过滤/排序。
答案 1 :(得分:0)
一种简单的方法(取决于您的用例)是在两个更新函数中将this.state.reports
替换为this.props.data
。 (尽管,如果这样做,则无法同时应用排序和过滤器)
但是我同意ModestLeech的观点,最好将过滤器存储在状态中。为此,请将您的过滤器代码更改为:
handleFilterType(event) {
this.setState({
filter: event.target.value;
})
});
}
在渲染方法中,假设您使用的是地图,则可以将地图更改为this.state.reports.filter(item => (this.state.filter===undefined || item.type===this.state.filter)).map(...)
。
编辑:
使用React需要担心两种类型的突变。
一个不是在改变道具(即,改变组件无法控制的状态)。由于Javascript通过引用传递数组和对象,因此如果您要在sort
上使用this.props.data
,它将实际上修改组件的父级(或祖父母级或定义的位置)中存在的数组。好消息是您的原始代码已经避免了这种情况-可能是偶然的情况。 handleSortBy
在对该数组进行突变之前对其进行了复制,handleFilterType
使用Array.prototype.filter
来创建一个新数组。
您需要担心的第二个突变是不使用setState
来更改本地状态。在this.state.reports.sort(...)
中调用render
会更改本地状态,但是React不会知道,也不会重新渲染。这不是问题,因为您在需要之前就进行了排序,但是直接改变状态是危险的,因为它可能导致错误,您作为开发人员认为某些情况下应该或不应进行更改,但实际情况有所不同
您最初的filter
问题与意外突变无关。问题在于,第一次使用过滤器调用this.setState
时,您重写了this.state.reports
,无法收回它。还有一个问题是,如果this.props.data
在父项中进行了更改,则新报表将永远不会出现在此组件中,因为您仅在首次创建组件时才读取道具。
推荐的React方法是不要存储来自prop的状态,除非您只是使用prop设置一些初始状态,并且所有将来的更新都将来自组件内部。但是,假设该组件最终并没有拥有报告列表,那么从长远来看,在this.props.data
中复制render
并对其进行排序和过滤会更简单。然后,如果在组件树的更高处添加或删除了任何内容,则无需编写任何特殊逻辑即可更新该组件的本地状态。