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

ユースケースに応じてこれを行う簡単な方法の 1 つは、2 つの update 関数this.state.reportsをに置き換えることです。this.props.data(ただし、この方法だとソートとフィルターを同時に適用することはできませんでした)

しかし、代わりにフィルターを状態に保存する方が良いという ModestLeech に同意します。これを行うには、フィルター コードを次のように変更します。

handleFilterType(event) {
    this.setState({
        filter: event.target.value;
        })
    });
}

render メソッドでは、マップを使用していると仮定して、マップを に変更できますthis.state.reports.filter(item => (this.state.filter===undefined || item.type===this.state.filter)).map(...)

編集:

React で考慮する必要があるミューテーションには 2 種類あります。

1 つは小道具を変更しないことです (つまり、コンポーネントが制御しない状態を変更します)。Javascript は参照によって配列とオブジェクトを渡すため、実際にコンポーネントの親 (または親の親、またはそれが定義されている場所) に存在する配列を変更しますsortthis.props.data良いニュースは、あなたの元のコードがすでにそれを回避していたことです - おそらく偶然に。 handleSortBy変更する前に配列のコピーを作成し、新しい配列を作成する をhandleFilterType使用します。Array.prototype.filter

心配しなければならない 2 番目の変更は、を使用せずにローカルの状態を変更することsetStateです。呼び出すとローカルの状態が変更this.state.reports.sort(...)されrenderますが、React は認識せず、再レンダリングしません。必要になる直前にソートしているので、これは問題ではありませんが、状態を直接変更することは危険です。なぜなら、開発者として、特定の条件下で何かを変更すべきか変更すべきではないと考えるバグにつながる可能性があるためですが、現実は異なります.

あなたの元の問題filterは、偶発的な突然変異とは何の関係もありませんでした。this.setState問題は、フィルターを使用して初めて呼び出すと、上書きthis.state.reportsしてしまい、元に戻す方法がないことでした。またthis.props.data、コンポーネントが最初に作成されたときにのみ props を読み取るため、親が変更された場合、新しいレポートがこのコンポーネントに表示されないという問題もありました。

これを行うための推奨される React の方法は、小道具を使用して初期状態を設定し、将来のすべての更新がコンポーネント内から行われる場合を除き、小道具からの状態に何かを保存しないことです。this.props.dataただし、このコンポーネントが最終的にレポートのリストを所有しないと仮定すると、長い目で見れば、 inのコピーを作成しrender、並べ替えとフィルターをそれに適用する方が簡単になります。その後、コンポーネント ツリーの上位に何かが追加または削除された場合、このコンポーネントのローカル状態を更新するための特別なロジックを記述する必要はありません。

于 2019-02-11T01:57:29.597 に答える