我有一个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);
答案 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>
);
}
}