2015-10-24 7 views
1

Я попытался сделать повторно используемый компонент в redux.
Идея заключается в том, что я создаю смарт-combobox и размещаю его несколько раз внутри другого компонента или интеллектуального компонента.Вложенные интеллектуальные компоненты в redux

Предполагается, что единственная работа из этой выписки - отображать страны, разрешить добавлять новые страны и сообщать родителям, какая страна выбрана.

Родитель не должен передавать доступным странам до выпадающего списка только событие onValueChanged, чтобы родитель знал, какая страна выбрана.

Это приводит к следующей структуре (элементы не на самом деле страны, чтобы держать это простой, но вы должны получить идею за ним):

//Constants (appConstants.ts) 
export const SmartCombobox = { 
    ADD_ITEM: 'SMART_COMBOBOX/ADD_ITEM' 
} 

//Action creator (smartComboboxAction.ts) 
import { SmartCombobox } from '../constants/appConstants'; 

export function AddItem() { 
    return { 
     type: SmartCombobox.ADD_ITEM 
    }; 
} 

//Reducer (smartCombobox.ts) 
import { SmartCombobox } from '../constants/appConstants'; 

const initialState = ['Item 1'] 

export default function items(state = initialState, action) { 
    switch (action.type) { 
     case SmartCombobox.ADD_ITEM: 
      let items = ['Item' + Math.random().toString()] 
      return state.concat(items); 
     default: 
      return state; 
    } 
} 

//Container (smartCombobox.ts) 
import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 
import { default as SmartCombobox } from '../components/combobox'; 
import * as ComboboxActions from '../actions/smartComboboxAction'; 

function mapStateToProps(state) { 
    return { 
     items: state.items   
    }; 
} 

function mapDispatchToProps(dispatch) { 
    return { 
     comboboxActions: bindActionCreators(<any>ComboboxActions, dispatch) 
    } 
} 

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

Тогда я могу использовать его, как это в моем компоненте или интеллектуальный компонент. Когда я добавляю новый элемент, каждый компонент, который включает мой smartCombobox, будет синхронизирован и имеет точное количество элементов.

//Component (combobox.tsx) 
import * as React from 'react'; 

interface SmartComboboxProps { 
    items?: Array<any>, 
    comboboxActions?: any, 
    onValueChanged: Function 
} 

export default class SmartCombobox extends React.Component<SmartComboboxProps, any> { 
    onValueChanged(event:any) { 
     let selectedValue = event.target.value; 
     const { onValueChanged } = this.props; 

     onValueChanged(selectedValue); 
    } 

    componentDidMount() { 
     // Call value changed for first selected item   
     this.props.onValueChanged(this.props.items[0]); 
    } 

    render() { 
     const { comboboxActions } = this.props; 

     let options = this.props.items.map(function (o) { 
      return <option key={o} value={o}>{o}</option> 
     }); 

     return (
      <div> 
       <select style={{ width: "200px" }} name="SmartCombobox" onChange={ this.onValueChanged.bind(this) } > 
        { options } 
       </select> 
       <button onClick={ comboboxActions.AddItem }>Add item</button> 
      </div> 
     ); 
    } 
} 

Final result (Image)

Является ли это правильный подход для повторно используемых компонентов?
Или могут быть какие-то подводные камни, которые я мог бы забыть?

Была также идея, что combobox должен быть подключен непосредственно к api, потому что приложение не должно знать, что происходит здесь.
Но это нарушило бы идею потока, потому что я должен был бы состояние внутри этого компонента и т.д.
Я был против этой идеи ...

+0

Я не думаю, что этот подход неправильный, если он работает. Я не думаю, что подключение компонента к API лучше, чем поддержание потока, потому что вы можете захотеть узнать где-нибудь еще в своем приложении при загрузке этих данных (например, если у вас был глобальный gif загрузки). С другой стороны, вы можете использовать веб-компоненты в реакции, и этот шаблон не является анти-шаблоном. Вы могли бы использовать полимерный компонент, который подключался к API для этого, и это было бы не самым худшим в мире. –

ответ

0

Является ли это правильный подход для повторно используемых компонентов? Возможно, у вас могут быть какие-нибудь подводные камни, возможно, я забыл

Этот подход хорош.

Была также идея, что combobox должен быть подключен непосредственно к api, потому что приложение не должно знать, что происходит здесь.

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

+0

Спасибо. Так и думал :). Теперь мне нужно подумать, нужно ли мне активировать действие для заполнения combobox в родительском компоненте или внутри интеллектуального combobox. Выгода будет заключаться в том, что действие будет отправлено только один раз, когда я вызову его в родительском после компонентаDidMount. – datoml

+0

«Одна вещь, о которой я должен сейчас подумать, - это если я должен запустить действие для заполнения combobox в родительском компоненте или внутри интеллектуального combobox'. Смарт-поле со списком должно быть заполнено из магазина redux.Не * внутри * просто 'redux-react'' @ connect' – basarat

+0

Извините, я имел в виду, где я должен вызвать действие для заполнения. Мой смарт-combobox уже подключен к магазину. Но когда я вызываю это действие внутри combobox после componentDidMount, он будет вызван 3 раза, например. Но когда я вызываю действие вне родителя в методе componentDidMount, оно будет вызвано только один раз. Но, возможно, есть шанс забыть об этом после того, как я вложу его в родителя. Персоналии, я бы предпочел, чтобы это вызвало. – datoml