2017-12-11 14 views
3

私は、一連のドロップダウンからの選択に基づいてプロットのリストをフィルタリングしている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

あなたのデータをフィルタリングしないでください。私はあなたがこの複雑なフィルタリングによってレンダリングフィルタリングで何らかの正義を還元しているとは確信していません。 'this.props.plotFilter(value)'が非同期アクションであることを忘れないでください。その後、 'filterPlots()'を後で直接呼び出すときに、まだ処理されません。あなたのplotFilterはフィルタを設定するだけで、レンダリングする直前にデータをフィルタリングするか、またはどこかで減速機でフィルタリングを作成しますが、現在どうしているのかはわかりません – Icepickle

答えて

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

const filterPlots = ?このままにしておくと、「Uncaught(約束事)ReferenceError:filterPlotsが定義されていません」というエラーがスローされます。 「const」を追加すると別のエラーが発生します。「filterPlots」は予期しないトークンです。コンポーネントの外に関数を定義し、それをコールバックとして呼び出すと、無限ループが作成されます。 –

+0

オハイオ州、申し訳ありませんが、それはthis.filterPlots()componetWillReceivePropsのように呼び出す必要があります、答えを –

+0

申し訳ありませんが、分かりません。 filterPlotsをrender()とcomponentWillReceiveProps()の両方で宣言しています。そしてあなたは "const"または "let"なしでそれを宣言しています。何がありますか? –

関連する問題