Javascript Redux:单个容器,多个组件

Javascript Redux:单个容器,多个组件,javascript,redux,react-redux,Javascript,Redux,React Redux,我对React和Redux都是新手,我对我正在处理的案例的最佳实践和技术解决方案都不确定。我使用的是Dan Abramov定义的“组件”和“容器” 我正在使用的组件是一个过滤器组件的小集合:一个输入文本字段和两个按钮,所有这些组件都过滤实体列表。我尝试了两种方法: 第一种方法:单个组件包含两种类型容器的三个实例,容器连接到相应的组件 这是我第一次做的。在这里,根组件如下所示: import React, { PropTypes, Component } from 'react'; import

我对React和Redux都是新手,我对我正在处理的案例的最佳实践和技术解决方案都不确定。我使用的是Dan Abramov定义的“组件”和“容器”

我正在使用的组件是一个过滤器组件的小集合:一个输入文本字段和两个按钮,所有这些组件都过滤实体列表。我尝试了两种方法:

第一种方法:单个组件包含两种类型容器的三个实例,容器连接到相应的组件

这是我第一次做的。在这里,根组件如下所示:

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;
以及相应的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;
import React,{PropTypes,Component}来自'React';
类FilterButton扩展组件{
render(){
返回(
{this.props.displayName}
)
}
}
FilterButton.propTypes={
活动:PropTypes.bool.isRequired,
displayName:PropTypes.string.isRequired,
onClick:PropTypes.func.isRequired,
过滤器名称:需要PropTypes.string.isRequired
};
导出默认过滤器按钮;
这种方法可行,但我认为不必创建两个不同的容器。这又让我第二次尝试

第二种方法:包含多个组件的单个容器

在这里,我制作了一个更大的容器:

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);
import React,{PropTypes,Component}来自'React';
从“../../Config”导入配置;
从'react redux'导入{connect};
从“../actions”导入{toggleFilter};
从“../components/FilterButton”导入FilterButton
从“../components/FilterInput”导入FilterInput
类FilterContainer扩展组件{
render(){
const{active,currentInput,onChange,onClick}=this.props;
返回(
)
}
}
const mapStateToProps=(state,ownProps)=>{
返回{
活动:!!state.program.filters[ownProps.filterName],
currentInput:state.program.filterName[ownProps.filterName]?state.program.filterName[ownProps.filterName]。输入:“”
}
}
const mapDispatchToProps=(调度,ownProps)=>{
返回{
onClick:()=>{
分派(切换过滤器(ownProps.filterName,ownProps.input))
},
onChange:newValue=>{
分派(toggleFilter(ownProps.filterName,newValue.target.value))
}
}
}
导出默认连接(
MapStateTops,
mapDispatchToProps
)(过滤器容器);
在这里,整个组件的所有状态交互都集中在一个组件中。这里的组件与第一种方法中的组件相同。但是,这并没有真正起作用:ownProps在MapStateTrops和mapDispathToProps中都是空的。我可能误解了react-redux连接的工作原理

因此,考虑到这些问题,我有两个问题:从容器和组件的角度来看,构造这个组件的最佳方式是什么?其次,为什么ownProps在第二种方法中的工作方式与第一种方法中的工作方式不同


谢谢您抽出时间。

目前我不确定是否有关于结构的具体答案。至于“ownProps”,它表示由父组件专门传递给给定组件的props。由于您是
connect()
-ing FilterController,这意味着“ownProps”将来自渲染该组件的任何地方,例如:
return

根据这些映射函数的编写方式,看起来您确实希望连接FilterInput和FilterButton组件,而不是FilterController

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