2016-02-23 17 views
7

Mam tablicę obiektów przechowywanych w redux. Chcę móc filtrować tę tablicę na podstawie danych wprowadzanych przez użytkownika. Czy powinienem utworzyć obiekt stanu, który odbiera tablicę za pomocą rekwizytów i modyfikuje tę tablicę, czy też jest to zła praktyka mieszania stanu i rekwizytów? Jeśli dobrze jest zmieszać te dwa, czy powinienem ustawić stan w componentWillReceiveProps?Najlepszy sposób filtrowania tabeli w React

+2

todomvc to bardzo logiczne podejście do śledzenia stanu filtrowania. Oto, jak to wygląda w reakcji/redux https://github.com/reactjs/redux/blob/master/examples/todomvc/components/MainSection.js – azium

+0

Szukam czegoś takiego https: // facebook. github.io/fixed-data-table/example-filter.html, z tym, że otrzymuję tablicę przez rekwizyty, zamiast mieć ją jako mój stan. – Juliuszc

+2

Dokładnie ta sama zasada obowiązuje jednak. Pamiętaj, twoje rekwizyty są czyimś stanem. Przechowujesz dane wejściowe użytkownika jako stan gdzieś .. albo redux albo w komponencie tabeli, a następnie filtruj tablicę rekwizytów względem tego stanu filtru. – azium

Odpowiedz

11

Stan budowy oparty na rekwizytach może być nieco skomplikowany, co jest dopuszczalne, ale należy wziąć pod uwagę wszystkie opcje.

Najprostszym rozwiązaniem jest filtrowanie rekwizytów w metodzie render. Jeśli masz wystarczająco małe elementy, które nie są aktualizowane przez zbyt wielu powodów, a zwłaszcza wtedy, gdy liczba elementów na liście jest niska, to może być korzystna metoda:

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

Kolejnym rozwiązaniem jest to, co opisujesz i wyprowadzasz stan obliczony na podstawie stanu filtra komponentu i rekwizytów przekazanych do niego. Jest to dobre, gdy masz skomplikowany komponent, który otrzymuje wiele rekwizytów i jest często renderowany. Tutaj buforujesz widoczne elementy i filtrujesz listę tylko wtedy, gdy trzeba ją odfiltrować.

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

I wreszcie, Redux „droga”, która wymaga, aby przekazać twórcy działania i filterStr jako rekwizyty do komponentu, prawdopodobnie został przekazany connect gdzieś indziej. Poniższa implementacja używa składnika bezstanowego, ponieważ nie zachowujemy w ogóle stanu komponentu 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

Dzięki za poświęcenie czasu, aby dogłębnie odpowiedzieć na to pytanie! – Juliuszc

+0

Pierwszy i trzeci przykład są całkiem dobre. Muszę jednak zająć się drugim przykładem. Twoje 'this.state.viewableEls' pochodzi wyłącznie z rekwizytów i stanów, podczas gdy pola stanu powinny zawierać unikatowe informacje. Twierdzisz, że ma to zaletę buforowania, ale ja tego nie widzę; ponieważ render jest wywoływany tylko wtedy, gdy rekwizyty/aktualizacja stanu w każdym razie. –

+0

W poprawnym przykładzie, masz rację, nie ma żadnej korzyści dla "buforowania", ale jeśli otrzymujesz inne rekwizyty, które wyzwalają 'render', ale które nie powinny wpływać na wartość' this.state.viewableEls', to jest. O ile oczywiście nie zrozumiałem cię źle. Powiedzmy, że 90% ponownych renderowań jest wyzwalanych przez zmianę rekwizytów, których 'viewableEls' nie jest funkcją (powiedzmy, że istnieje składnik czatu w czasie rzeczywistym, który jest dzieckiem), a' elementy' są w w zakresie dziesiątek tysięcy elementów, za każdym razem, gdy pojawi się nowa wiadomość, nie będzie trywialnej, lecz niepotrzebnej ponownej kalibracji. Nie? –

Powiązane problemy