0

我有一个简单的组件,它从一组对象构建报告列表,我正在尝试添加过滤和排序功能(在一定程度上确实有效),排序功能有效,但我担心我正在变异尽管试图将原始状态复制到新数组中。

我的过滤器第一次工作,但它不会过滤其他结果,因为状态已经发生变化,或者因为我无法过滤初始状态?这让我困惑了几个小时,非常感谢任何帮助。

非常感谢

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;
        })
    });
}

提前致谢 :)

4

2 回答 2

0

我认为问题在于每次过滤时,您都会从中删除项目state.reports,并且永远不会从props.data.

相反,您应该state.reportsprops.data每次过滤/排序时重新构建。

或者,IMO 更好的方法是将过滤/排序设置存储在 中,state并根据当前设置进行过滤/排序。props.datarender

于 2019-02-11T01:48:00.450 回答
0

根据您的用例,一种简单的方法是在您的两个更新函数中替换this.state.reports为。this.props.data(虽然,如果你这样做,你不能同时应用排序和过滤)

但我同意 ModestLeech 的观点,即最好将过滤器存储在 state 中。为此,请将您的过滤器代码更改为:

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 通过引用传递数组和对象,如果您要这样做,sortthis.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 的 state 中存储一些东西,除非你只是使用 prop 来设置一些初始状态,并且所有未来的更新都来自组件内部。但是假设这个组件最终不拥有报表列表,从长远来看,复制this.props.datainrender并将您的排序和过滤器应用于它会更简单。然后,如果在组件树的更高位置添加或删除任何内容,您将无需编写任何特殊逻辑来更新此组件的本地状态。

于 2019-02-11T01:57:29.597 回答