Я попытался сделать повторно используемый компонент в 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>
);
}
}
Является ли это правильный подход для повторно используемых компонентов?
Или могут быть какие-то подводные камни, которые я мог бы забыть?
Была также идея, что combobox должен быть подключен непосредственно к api, потому что приложение не должно знать, что происходит здесь.
Но это нарушило бы идею потока, потому что я должен был бы состояние внутри этого компонента и т.д.
Я был против этой идеи ...
Я не думаю, что этот подход неправильный, если он работает. Я не думаю, что подключение компонента к API лучше, чем поддержание потока, потому что вы можете захотеть узнать где-нибудь еще в своем приложении при загрузке этих данных (например, если у вас был глобальный gif загрузки). С другой стороны, вы можете использовать веб-компоненты в реакции, и этот шаблон не является анти-шаблоном. Вы могли бы использовать полимерный компонент, который подключался к API для этого, и это было бы не самым худшим в мире. –