2015-12-20 46 views
11

Come visto here Sto provando a disaccoppiare i componenti della mia app il più possibile ea non renderli consapevoli di alcun creatore di archiviazione o azione.Disaccoppiamento Componenti Reagire e Connessione Redux

L'obiettivo è farli gestire il proprio stato e chiamare le funzioni per emettere un cambiamento. Mi è stato detto che lo fai usando gli oggetti di scena.

Considerando

// Menu.jsx 

import React from 'react' 
import { className } from './menu.scss' 
import Search from 'components/search' 

class Menu extends React.Component { 
    render() { 
    return (
     <div className={className}> 
     <a href='#/'>Home</a> 
     <a href='#/foo'>foo</a> 
     <a href='#/bar'>bar</a> 
     <Search /> 
     </div> 
    ) 
    } 
} 

E

// Search.jsx 

import React from 'react' 
import { className } from './search.scss' 

class Search extends React.Component { 
    render() { 
    let { searchTerm, onSearch } = this.props 

    return (
     <div className={`search ${className}`}> 
     <p>{searchTerm}</p> 
     <input 
      type='search' 
      onChange={(e) => onSearch(e.target.value)} 
      value={searchTerm} 
     /> 
     </div> 
    ) 
    } 
} 

Search.propTypes = { 
    searchTerm: React.PropTypes.string, 
    onSearch: React.PropTypes.function 
} 

export default Search 

E leggere here vedo un uso intelligente di Provider e connect e la mia implementazione sarebbe simile a questa:

import { bindActionCreators, connect } from 'redux' 
import actions from 'actions' 

function mapStateToProps (state) { 
    return { 
    searchTerm: state.searchTerm 
    } 
} 

function mapDispatchToProps (dispatch) { 
    return bindActionCreators({ 
    dispatchSearchAction: actions.search 
    }, dispatch) 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Search) 

Assumendo I avere un negozio che gestisce searchTerm come parte dello stato globale.

Il problema è, dove si trova questo codice? Se lo metto in Search.jsx accoppierò le azioni con il componente e più importante a redux.

Dovrei avere due versioni diverse del mio componente, una disaccoppiata e una connect() ed avere <Menu /> per usarla? Se sì, come sarebbe il mio albero di file? Un file per componente o simile a make-all-connected.js?

risposta

10

In redux, esiste un nuovo tipo di componente chiamato contenitori, questo è il componente che utilizza connect (mapStateToProps, mapActionsToProps), per passare lo stato e le azioni al componente corrente.

Tutto dipende dall'utilizzo del componente. Ad esempio, se si componente Ricerca solo andando a essere utilizzato con lo stesso stato e l'azione, Tu contenitore potrebbe essere lo stesso che il componente in questo modo:

// Search.jsx 
import { connect } from 'redux' 
import actions from 'actions' 
import React from 'react' 
import { className } from './search.scss' 

class Search extends React.Component { 
    render() { 
    let { searchTerm, onSearch } = this.props 

    return (
     <div className={`search ${className}`}> 
     <p>{searchTerm}</p> 
     <input 
      type='search' 
      onChange={(e) => onSearch(e.target.value)} 
      value={searchTerm} 
     /> 
     </div> 
    ) 
    } 
} 

Search.propTypes = { 
    searchTerm: React.PropTypes.string, 
    onSearch: React.PropTypes.function 
} 


function mapStateToProps ({searchTerm}) { 
    return { 
    searchTerm 
    }; 
} 

const mapDispatchToProps = { 
    onSearch: actions.search 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Search) 

Ma se il vostro piano è riutilizzare questa componente di un altro i contenitori e il searchTerm o l'azione sono diversi sullo stato globale. Il modo migliore è passare queste proprietà attraverso altri contenitori e mantenere puro il componente di ricerca. Come questo:

// Container1.jsx 
import { connect } from 'redux' 
import actions from 'actions' 
import React, { Component } from 'react' 

class Container1 extends Component { 
    render() { 
    const { searchTerm, handleOnSearch } = this.props; 
    return (
     <div> 
     <Search searchTerm={searchTerm} onSearch={handleOnSearch} /> 
     </div> 
    ) 
    } 
} 

function mapStateToProps ({interState: {searchTerm}}) { 
    return { 
    searchTerm 
    }; 
} 

const mapDispatchToProps = { 
    handleOnSearch: actions.search 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Container1) 

// Container2.jsx 
import { connect } from 'redux' 
import otherActions from 'otheractions' 
import React, { Component } from 'react' 

class Container2 extends Component { 
    render() { 
    const { searchTerm, handleOnSearch } = this.props; 
    return (
     <div> 
     <Search searchTerm={searchTerm} onSearch={handleOnSearch} /> 
     </div> 
    ) 
    } 
} 

function mapStateToProps ({otherState: {searchTerm}}) { 
    return { 
    searchTerm 
    }; 
} 

const mapDispatchToProps = { 
    handleOnSearch: otherActions.search 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Container2) 

Per ulteriori informazioni, leggere l'official docs about using redux with react.

+1

Grazie, mentre in generale questo è corretto, sarei grato se potessi aggiungere http://rackt.org/redux/docs/basics/UsageWithReact.html nella risposta, quindi lo contrassegnerò come corretto – kilianc

+1

I don non ho problemi Aggiunto. –

Problemi correlati