Q:

React Redux filtering lags a step

I have a React Redux connected component which is filtering a list of plots based on selections from a series of dropdowns.
It is behaving quite strangely-it filters based not on the current but on the previous selection. Meaning, if I have a list of plots and select "region A," it will show me the same, unfiltered list of plots. However, if I then select "region B," it will show me plots belonging to region A. If I then select "region C," it will show me plots belonging to region B. 
There is some kind of logical error in my code, but I'm not seeing it. Can anyone spot it?
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);

A:

The problem occurs because you are trying to filter immediately after change with the current props, but the props are updating in the parent and you should wait for them to update before you call filter. You could do it by making use of componentWillReceiveProps like below
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>
        );
    }
}

