2016-02-23 11 views
7

私はreduxに格納されたオブジェクトの配列を持っています。私は、ユーザーの入力に基づいて配列をフィルタリングできるようにしたい。私は、小道具を介して配列を受け取り、その配列を変更する状態オブジェクトを作成すべきですか、または状態と小道具を混在させることは悪い習慣ですか? 2つを混在させても問題ない場合は、componentWillReceivePropsに状態を設定する必要がありますか?Reactでテーブルをフィルタリングする最良の方法

+2

todomvcは、状態をフィルタリングするための非常に論理的なアプローチです。 react/reduxで見えるものは次のとおりです。https://github.com/reactjs/redux/blob/master/examples/todomvc/components/MainSection.js – azium

+0

私はこのhttps:// facebookのようなものをもっと探しています。 github.io/fixed-data-table/example-filter.html、私は代わりに私の状態として持っているの小道具を介して配列を受け取ります。 – Juliuszc

+2

しかし、まったく同じ原則が適用されます。あなたの小道具は誰かの国家であることを忘れないでください。ユーザー入力はどこかの状態で格納されます。reduxまたはテーブルコンポーネントに格納され、そのフィルタ状態に対してプロップ配列がフィルタリングされます。 – azium

答えて

11

小道具に基づく建物の状態は多少複雑になる可能性がありますが、すべての選択肢を考慮する必要があります。

実装するのが最も簡単なのは、renderメソッドで小道具をフィルタリングすることです。

class FilterList extends React.Component { 
    render() { 
    const { elements } = this.props; 
    const { filterStr } = this.state; 

    const filteredElements = elements 
     .filter(e => e.includes(filterStr)) 
     .map(e => <li>{ e }</li>) 

    return (
     <div> 
     <input 
      type="text" 
      value={ filterStr } 
      onChange={ e => this.setState({ filterStr: e.target.value }) } /> 
     <ul> 
      { filteredElements } 
     </ul> 
     </div> 
    ); 
    } 
} 

次のオプションが何をすべきかです:あなたはあまりにも多くの理由のために更新されませんし、リスト内の要素の数が少ない場合は特に、これは好ましい方法であるかもしれない十分に小さい部品を使用している場合あなたは記述しており、コンポーネントのフィルタ状態と渡された小道具に基づいて計算された状態を導出します。これは、多くの小道具を受け取り、頻繁にレンダリングされる複雑なコンポーネントを使用している場合に適しています。ここでは、表示可能な要素をキャッシュし、フィルタリングが必要なときにのみリストをフィルタリングします。

class FilterList extends React.Component { 
    constructor (props) { 
    this.state = { 
     viewableEls: props.elements 
    } 
    } 

    componentWillReceiveProps (nextProps) { 
    const { elements } = this.props; 
    const { filterStr } = this.state; 

    if (elements !== nextProps.elements) { 
     this.setState({ 
     viewableEls: this.getViewableEls(nextProps.elements, filterStr) 
     }) 
    } 
    } 

    getViewableEls (elements, filterStr) { 
    return elements.filter(el => el.includes(filterStr)) 
    } 

    handleFilterChange = e => { 
    const { elements } = this.props; 

    this.setState({ 
     filterStr: e.target.value, 
     viewableEls: this.getViewableEls(elements, filterStr) 
    }) 
    } 
    render() { 
    const { viewableEls } = this.state; 

    return (
     <div> 
     <input 
      type="text" 
      value={ filterStr } 
      onChange={ e => this.setState({ filterStr: e.target.value }) } /> 
     <ul> 
      { viewableEls.map(e => <li key={ e }>{ e }</li>) } 
     </ul> 
     </div> 
    ); 
    } 
} 

そして最後に、おそらくどこかconnect経由で渡されたコンポーネントの小道具としてアクションの作成者とfilterStrに合格する必要がありますReduxの「道」、。以下の実装では、ステートレスコンポーネントを使用しています。なぜなら、我々はコンポーネントの状態に全くfitlerStrを保持していないからです。

const FilterTable = ({ elements, filterStr, changeFilterStr }) => { 
    return (
    <div> 
     <input 
     type="text" 
     value={ filterStr } 
     onChange={ e => changeFilterStr(e.target.value) } /> 
     <ul> 
     { 
      elements 
      .filter(e => e.includes(filterStr)) 
      .map(e => <li key={ e }>{ e }</li>) 
     } 
     </ul> 
    </div> 
) 
} 
+0

深く疑問に答える時間を入れてくれてありがとう! – Juliuszc

+0

第1と第3の例はかなり良いです。私はしかし、2番目の例で問題を起こさなければならない。あなたの 'this.state.viewableEls'はpropsとstateから完全に得られますが、stateフィールドは本当にユニークな情報を含んでいなければなりません。これにキャッシュの利点があると主張しますが、私はそれを見ません。とにかくprops/stateが更新されたときにのみレンダリングが開始されるからです。 –

+0

実際の例では正しいと思いますが、 'キャッシング'には何のメリットもありませんが、 'render'をトリガーする他のプロップを受け取っていて、' this.state.viewableEls'の値に影響を与えない場合は、それがあります。もちろん、私があなたを誤解していない限り。再レンダリングの90%が、 'viewableEls'が(チャットコンポーネントが子であると言うことができる)関数ではないプロップの変更によって引き起こされ、' elements'は数万の要素の範囲では、新しいメッセージが届くたびに、些細ではありませんが再処理が必要になります。いいえ? –

関連する問題