2016-04-06 13 views
1

Ich bin ziemlich neu in React und Redux, und ich bin unsicher über beide Best Practices und die technische Lösung für einen Fall, an dem ich arbeite. Ich verwende "Komponente" und "Container" wie von Dan Abramov here definiert.Redux: Einzelner Container, mehrere Komponenten

Die Komponente, an der ich arbeite, ist eine kleine Sammlung von Filterkomponenten: Ein Eingabetextfeld und zwei Schaltflächen, die alle eine Liste von Entitäten filtern. Ich habe zwei Ansätze ausprobiert:

Erster Ansatz: Einzelne Komponente enthält drei Instanzen von zwei Arten von Containern, Container mit entsprechenden Komponenten verbunden.

Das war, was ich zuerst gemacht habe. Hier sieht die Root-Komponente wie folgt aus:

import React, { PropTypes, Component } from 'react'; 
import Config from '../../config'; 
import FilterInput from '../containers/FilterInput'; 
import FilterLink from '../containers/FilterLink' 

class FilterController extends Component { 
    render() { 
     return (
      <div className='filterController'> 
       <FilterInput displayName="Search" filterName={Config.filters.WITH_TEXT} /> 
       <FilterLink displayName="Today" filterName={Config.filters.IS_TODAY} /> 
       <FilterLink displayName="On TV" filterName={Config.filters.ON_TV} /> 
      </div> 
     ) 
    } 
} 
export default FilterController; 

Die beiden hier referenzierten Container sehen genauso aus wie die angeschlossenen Komponenten. Ich werde die FilterLink als Beispiel zeigen:

import React, { PropTypes, Component } from 'react'; 
import {connect} from 'react-redux'; 
import {toggleFilter} from '../actions'; 
import FilterButton from '../components/filterbutton' 

const mapStateToProps = (state, ownProps) => { 
    return { 
     active: !!state.program.filters[ownProps.filterName] 
    } 
} 

const mapDispatchToProps = (dispatch, ownProps) => { 
    return { 
     onClick:() => { 
      dispatch(toggleFilter(ownProps.filterName, ownProps.input)) 
     } 
    } 
} 

const FilterLink = connect(
    mapStateToProps, 
    mapDispatchToProps 
)(FilterButton) 

export default FilterLink 

und die entsprechende FilterButton Komponente:

import React, { PropTypes, Component } from 'react'; 

class FilterButton extends Component { 

    render() { 
     return (
      <button className={this.props.active ? 'active' : ''} 
        onClick={this.props.onClick}> 
       {this.props.displayName} 
      </button> 
     ) 
    } 
} 

FilterButton.propTypes = { 
    active: PropTypes.bool.isRequired, 
    displayName: PropTypes.string.isRequired, 
    onClick: PropTypes.func.isRequired, 
    filterName: PropTypes.string.isRequired 
}; 

export default FilterButton; 

Dieser Ansatz funktioniert, aber ich denke, dass es nicht notwendig sein sollte zwei verschiedene erstellen Behälter. Was mich wiederum zu meinem zweiten Versuch führte.

Zweiter Ansatz: einzelner Container mit mehreren Komponenten.

Hier habe ich einen größeren Behälter:

import React, { PropTypes, Component } from 'react'; 
import Config from '../../config'; 
import {connect} from 'react-redux'; 
import {toggleFilter} from '../actions'; 
import FilterButton from '../components/filterbutton' 
import FilterInput from '../components/filterinput' 

class FilterContainer extends Component { 
    render() { 
     const { active, currentInput, onChange, onClick } = this.props; 
     return (
      <div className='filterController'> 
       <FilterInput displayName="Search" filterName={Config.filters.WITH_TEXT} currentInput={currentInput} onChange={onChange} /> 
       <FilterButton displayName="Today" filterName={Config.filters.IS_TODAY} active={active} onClick={onClick}/> 
       <FilterButton displayName="On TV" filterName={Config.filters.ON_TV} active={active} onClick={onClick}/> 
      </div> 
     ) 
    } 
} 

const mapStateToProps = (state, ownProps) => { 
    return { 
     active: !!state.program.filters[ownProps.filterName], 
     currentInput: state.program.filters[ownProps.filterName] ? state.program.filters[ownProps.filterName].input : '' 
    } 
} 

const mapDispatchToProps = (dispatch, ownProps) => { 
    return { 
     onClick:() => { 
      dispatch(toggleFilter(ownProps.filterName, ownProps.input)) 
     }, 
     onChange: newValue => { 
      dispatch(toggleFilter(ownProps.filterName, newValue.target.value)) 
     } 
    } 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(FilterContainer); 

Hier werden alle staatlichen Interaktion für das gesamte Bauteil wird in einem einzigen compoment gesammelt. Die Komponenten sind hier die gleichen wie beim ersten Ansatz. Dies funktioniert jedoch nicht wirklich: ownProps ist sowohl in mapStateToProps als auch in mapDispathToProps leer. Ich habe vielleicht mißverstanden, wie die react-redux-Verbindung funktioniert.

So, habe ich zwei Fragen: Was ist der beste Weg, um diese Komponente in Bezug auf Container und Komponenten zu strukturieren? Und zweitens, warum wird in der zweiten Methode nicht wie in der ersten die eigene Methode funktionieren?

Vielen Dank für Ihre Zeit.

Antwort

1

Nicht sicher, dass ich eine spezifische Antwort bezüglich der Struktur im Moment habe. Wie bei "ownProps" stellt das Requisiten dar, die von einer übergeordneten Komponente an eine bestimmte Komponente übergeben werden. Da du connect() -ing FilterController bist, heißt das, dass "ownProps" von wo auch immer du diese Komponente rendern würdest, wie: return <FilterController prop1="a" prop2={someVariable} />.

Je nachdem, wie Sie diese Map-Funktionen geschrieben haben, sieht es so aus, als wollten Sie wirklich die FilterInput- und FilterButton-Komponenten anstelle von FilterController verbinden.

Verwandte Themen