2015-12-20 2 views
11

Как видно here Я стараюсь как можно больше разделить компоненты моего приложения и не сообщать им о каком-либо создателе хранилища или действия.Развязывающие компоненты React и Redux Connect

Цель состоит в том, чтобы заставить их управлять своим состоянием и функциями вызова, чтобы испустить изменения. Мне сказали, что вы делаете это с помощью реквизита.

Учитывая

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

И

// 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 

И чтение here я вижу умный использование Provider и connect и моей реализации будет выглядеть примерно так:

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) 

Если предположить, что иметь складскую обработку searchTerm как часть глобального государства.

Проблема в том, где принадлежит этот код? Если я поставлю его в Search.jsx, я буду сочетать действия с компонентом и более важным для redux.

Возможно, у меня две разные версии моего компонента, одна развязана и одна connect() ed и есть <Menu />, чтобы использовать ее? Если да, то каким будет выглядеть дерево файлов? Один файл на один компонент или вроде make-all-connected.js?

ответ

10

В redux существует новый вид компонента, который называется контейнером, это компонент, который использует connect (mapStateToProps, mapActionsToProps), чтобы передать состояние и действия текущему компоненту.

Все зависит от использования компонента. Например, если вы компонент Поиска только будете использовать в том же состоянии и действие, вы контейнер может быть таким же, что компонент, как это:

// 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) 

Но если ваш план повторно использовать этот компонент в другом контейнеры и searchTerm или действие различны в глобальном состоянии. Лучший способ - передать эти свойства через другие контейнеры и сохранить компонент поиска чистым. Например:

// 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) 

Для получения дополнительной информации, прочитайте official docs about using redux with react.

+1

Спасибо, хотя, вообще говоря, это правильно, я был бы признателен, если бы вы могли добавить http://rackt.org/redux/docs/basics/UsageWithReact.html в ответ, тогда я отметю его как правильно – kilianc

+1

У меня проблемы. Добавлен. –

Смежные вопросы