2016-02-23 9 views
7

Ho una matrice di oggetti memorizzati in redux. Voglio essere in grado di filtrare quell'array in base all'input dell'utente. Dovrei creare un oggetto di stato che riceve l'array attraverso i puntelli e modificare quella matrice, o è una cattiva pratica mescolare stato e oggetti di scena? Se è giusto mescolare i due, dovrei impostare lo stato in componentWillReceiveProps?Il modo migliore per filtrare la tabella in React

+2

todomvc è un approccio molto logico da seguire per lo stato di filtraggio. ecco come appare con react/redux https://github.com/reactjs/redux/blob/master/examples/todomvc/components/MainSection.js – azium

+0

Sto cercando qualcosa di simile a questo https: // facebook. github.io/fixed-data-table/example-filter.html, eccetto che sto ricevendo l'array tramite oggetti di scena invece di averlo come stato. – Juliuszc

+2

Esattamente lo stesso principio si applica però. Ricorda, i tuoi oggetti di scena sono lo stato di qualcun altro. Si memorizza l'input dell'utente come stato da qualche parte ... o redux o nel componente table, quindi si filtra l'array props contro quello stato del filtro. – azium

risposta

11

Lo stato di edificio basato su oggetti di scena può essere alquanto complicato, il che è accettabile, ma è necessario considerare tutte le opzioni.

Il modo più semplice per implementare è filtrare i puntelli nel metodo render. Se si dispone di abbastanza piccoli componenti che non aggiornamento per troppe ragioni, e soprattutto se il numero di elementi nella lista è basso, questo potrebbe essere il metodo preferito:

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

L'opzione successiva è di fare ciò stai descrivendo e ricavando uno stato calcolato in base allo stato del filtro del componente e agli oggetti di scena passati ad esso. Questo è buono quando hai un componente complicato che riceve molti oggetti di scena e viene reso spesso. Qui, stai memorizzando nella cache gli elementi visibili e filtrando solo l'elenco quando deve essere filtrato.

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

E, infine, il redux 'modo', che richiede di passare il creatore azione e filterStr come oggetti di scena al componente, probabilmente passati in via connect da qualche altra parte. L'implementazione seguente utilizza un componente stateless poiché non stiamo mantenendo lo fitlerStr nello stato del componente.

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

Grazie per aver dedicato del tempo per rispondere alla domanda in profondità! – Juliuszc

+0

Il primo e il terzo esempio sono abbastanza buoni. Devo tuttavia prendere in considerazione il secondo esempio. Il tuo 'this.state.viewableEls' è interamente derivato da oggetti di scena e stato, mentre i campi di stato dovrebbero contenere davvero pezzi di informazione unici. Lei sostiene che questo ha un vantaggio nella cache, ma io non lo vedo; dal momento che un rendering viene attivato solo quando l'aggiornamento puntelli/stato è comunque aggiornato. –

+0

Nell'esempio inventato, sei corretto, non vi è alcun vantaggio nel "caching", ma se stai ricevendo altri oggetti di scena che attivano 'render', ma che non dovrebbe influenzare il valore di' this.state.viewableEls', allora c'è. A meno che non ti stia fraintendendo, naturalmente. Diciamo che il 90% dei re-rendering è attivato dal cambiamento di un puntello che 'viewableEls' non è una funzione di (diciamo che c'è un componente di chat in tempo reale che è un bambino), e' elements' è in Nel raggio di decine di migliaia di elementi, ci sarà una ricalibrazione non banale ma non necessaria ogni volta che un nuovo messaggio arriva. No? –

Problemi correlati