私は React と Redux の両方にまったく慣れていないため、取り組んでいるケースのベスト プラクティスと技術的な解決策の両方について確信が持てません。ここでは、Dan Abramov によって定義されている「コンポーネント」と「コンテナー」を使用しています。
私が取り組んでいるコンポーネントは、フィルター コンポーネントの小さなコレクションです。1 つの入力テキスト フィールドと 2 つのボタンで、すべてエンティティのリストをフィルター処理します。私は2つのアプローチを試しました:
最初のアプローチ: 2 つのタイプのコンテナーの 3 つのインスタンスを含む単一のコンポーネント (対応するコンポーネントに接続されたコンテナー)。
最初に作ったのはこれでした。ここで、ルート コンポーネントは次のようになります。
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;
ここで参照されている 2 つのコンテナーは、接続されたコンポーネントと同様に、ほとんど予想どおりに見えます。例として FilterLink を示します。
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
対応する FilterButton コンポーネント:
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;
このアプローチは機能しますが、2 つの異なるコンテナーを作成する必要はないと考えています。それが再び私を2回目の試みに導きました。
2 番目のアプローチ: 複数のコンポーネントを含む単一のコンテナー。
ここでは、より大きなコンテナを作成しました。
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);
ここでは、コンポーネント全体のすべての状態相互作用が 1 つのコンポーネントにまとめられています。ここでのコンポーネントは、最初のアプローチと同じです。ただし、これは実際には機能しません。ownProps は mapStateToProps と mapDispathToProps の両方で空です。react-redux 接続の仕組みを誤解している可能性があります。
これらのことを考えると、2 つの質問があります。コンテナーとコンポーネントの観点から、このコンポーネントを構造化する最良の方法は何ですか? 次に、2 番目のアプローチで ownProps が最初のアプローチと同様に機能しないのはなぜですか?
お時間をいただきありがとうございます。