React Redux过滤滞后一步

时间:2017-12-11 11:50:35

标签: javascript reactjs redux react-redux

我有一个React Redux连接组件,它根据一系列下拉列表中的选择过滤一个图表列表。

它的表现非常奇怪 - 它不是基于当前的过滤而是基于先前的选择过滤。这意味着,如果我有一个图表列表并选择"区域A,"它会显示相同的,未经过滤的情节列表。但是,如果我然后选择"区域B,"它将显示属于区域A的图。如果我然后选择"区域C,"它会告诉我属于B区的情节。

我的代码中存在某种逻辑错误,但我没有看到它。有谁能发现它?

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import { Multiselect } from 'react-widgets';
import 'react-widgets/dist/css/react-widgets.css';

const regions = props => {
    if (props.plots) {
        return Array.from([...new Set(props.plots.map(a => a.region))]);
    }
    return [];
};

const growers = props => {
    if (props.plots) {
        return Array.from([...new Set(props.plots.map(a => a.grower))]);
    }
    return [];
};
const varieties = props => {
    if (props.plots) {
        return Array.from([...new Set(props.plots.map(a => a.variety))]);
    }
    return [];
};
const plotNames = props => {
    if (props.plots) {
        return Array.from([...new Set(props.plots.map(a => a.name))]);
    }
    return [];
};

export class PlotFilterSearch extends Component {
    render() {
        const filters = [
            { prop: 'region', filterArray: this.props.regionFilterArray },
            { prop: 'grower', filterArray: this.props.growerFilterArray },
            { prop: 'variety', filterArray: this.props.varietyFilterArray },
            { prop: 'name', filterArray: this.props.plotNameFilterArray }
        ];

        const filterPlots = () => {
            if (this.props.plots) {
                let filteredPlots = [...this.props.plots];
                filters.forEach(filterObj => {
                    filteredPlots = filteredPlots.filter(
                        a =>
                            (filterObj.filterArray || []).length === 0 ||
                            filterObj.filterArray.includes(a[filterObj.prop])
                    );

                    console.log('filtered plots: ', filteredPlots);
                });
                this.props.storeFilteredPlots(filteredPlots);
            }
        };

        return (
            <div className="plotFilterSearch d-flex col flex-column justify-content-around mt-1 mb-1">
                <div className="multiSelectHolder">
                    <Multiselect
                        data={regions(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Regions"
                        onChange={value => {
                            this.props.regionFilter(value);
                            filterPlots();
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={growers(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Growers"
                        onChange={value => {
                            this.props.growerFilter(value);
                            filterPlots();
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={varieties(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Varieties"
                        onChange={value => {
                            this.props.varietyFilter(value);
                            filterPlots();
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={plotNames(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Plots"
                        onChange={value => {
                            this.props.plotFilter(value);
                            filterPlots();
                        }}
                    />
                </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        plots: state.plots.plots,
        filteredPlots: state.plots.filteredPlots,
        varietyFilterArray: state.plots.varietyFilter,
        regionFilterArray: state.plots.regionFilter,
        growerFilterArray: state.plots.growerFilter,
        plotNameFilterArray: state.plots.plotNameFilter
    };
}

export default connect(mapStateToProps, actions)(PlotFilterSearch);

1 个答案:

答案 0 :(得分:1)

出现问题是因为您尝试使用当前道具更改后立即过滤,但道具正在父级中更新,您应该在调用过滤器之前等待它们更新。您可以通过使用componentWillReceiveProps,如下所示

来实现
export class PlotFilterSearch extends Component {
    componentWillReceiveProps(nextProps) {
        if(
          this.props.plotNameFilterArray !== nextProps.plotNameFilterArray ||
        this.props.varietyFilterArray !== nextProps.varietyFilterArray ||
        this.props.growerFilterArray !== nextProps.growerFilterArray ||
        this.props.regionFilterArray !== nextProps.regionFilterArray
         ) {
            this.filterPlots(nextProps);
         }
    }


        filterPlots = (props) => {
            const filters = [
              { prop: 'region', filterArray: props.regionFilterArray },
              { prop: 'grower', filterArray: props.growerFilterArray },
              { prop: 'variety', filterArray: props.varietyFilterArray },
              { prop: 'name', filterArray: props.plotNameFilterArray }
          ];
            if (props.plots) {
                let filteredPlots = [...props.plots];
                filters.forEach(filterObj => {
                    filteredPlots = filteredPlots.filter(
                        a =>
                            (filterObj.filterArray || []).length === 0 ||
                            filterObj.filterArray.includes(a[filterObj.prop])
                    );

                    console.log('filtered plots: ', filteredPlots);
                });
                props.storeFilteredPlots(filteredPlots);
            }
        };
    render() {


        return (
            <div className="plotFilterSearch d-flex col flex-column justify-content-around mt-1 mb-1">
                <div className="multiSelectHolder">
                    <Multiselect
                        data={regions(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Regions"
                        onChange={value => {
                            this.props.regionFilter(value);
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={growers(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Growers"
                        onChange={value => {
                            this.props.growerFilter(value);
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={varieties(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Varieties"
                        onChange={value => {
                            this.props.varietyFilter(value);
                        }}
                    />
                </div>
                <div className="multiSelectHolder">
                    <Multiselect
                        data={plotNames(this.props)}
                        caseSensitive={false}
                        minLength={1}
                        filter="contains"
                        placeholder="Plots"
                        onChange={value => {
                            this.props.plotFilter(value);
                        }}
                    />
                </div>
            </div>
        );
    }
}