具有相同可重用redux的多个实例在同一页面/路由上反应组件

时间:2017-03-20 14:35:00

标签: redux

我们正在创建一个大型前端应用程序。

我们正在使用React-Redux

我们正在创建一些可重用的组件。

**这个问题是关于在同一页面/路线上有多个相同的可重复使用的redux反应组件的实例**

问题详情:

我们有一个Sectionheader组件。它与redux状态绑定。

它侦听header属性reducer SectionheaderReducer。

由于我们在页面上有2个此Sectionheader实例,因此它们都会显示相同的值,因为它们绑定到同一个store-property。

如何使基于redux的可重用反应组件可配置。因此每个实例可以为减速器具有不同的header属性值SectionheaderReducer

4 个答案:

答案 0 :(得分:34)

您需要实现一些命名空间实例的方法。这可以像传入一个键来区分组件和减速器一样基本。

您可以使用ownProps函数中的mapStateToProps来指导映射到命名空间

const mapStateToProps = (state, ownProps) {
    let myState = state[ownProps.namespace]
    return {
        myState.value
    }
}

可以使用相同的方法将命名空间传递给mapDispatchToProps

const mapDispatchToProps = (dispatch, ownProps) {
    return {
        myAction: (myParam) => dispatch(myAction(ownProps.namespace, myParam))
    }
}

请记住在动作类型中使用命名空间,以便减速器不会踩到脚趾

const myAction => (namespace, myParam) {
    return { type: `${namespace}/${MY_TYPE_CONSTANT}`, myParam }
}

并确保reducer也是命名空间

const myReducer = (namespace) => (state = initialState, action) => {
    switch(action.type) {
        case `${namespace}/${MY_TYPE_CONSTANT}`:
            return { ...state, action.myParam }
        default:
            return state
    {
}

现在在组合reducers

时添加2个名称空间缩减器
combineReducers({
    myInstance1 : myReducer('myInstance1')
    myInstance2 : myReducer('myInstance2')
}

最后将命名空间传递给每个实例

render() {
    return (
        <div>
            <MyComponent namespace='myInstance1' />
            <MyComponent namespace='myInstance2' />
        </div>
    )
}

免责声明:我是以下图书馆的主要撰稿人。

redux-subspace可以提供更高级的命名空间实现,而无需为希望拥有多个实例的每个组件重新实现此模式。

创建reducer与上面的类似

const reducer = combineReducers({ 
    myInstance1: namespaced('myInstance1')(myReducer)
    myInstance2: namespaced('myInstance2')(myReducer)
})

然后SubspaceProvider可用于切换每个组件的状态

render() {
    return (
        <div>
            <SubspaceProvider mapState={state => state.myInstance1} namespace='myInstance1'>
                <MyComponent />
            </SubspaceProvider>
            <SubspaceProvider mapState={state => state.myInstance2} namespace='myInstance2'>
                <MyComponent />
            </SubspaceProvider>
        </div>
    )
}

确保您还要更改mapStateToProps函数,以便从提供程序中映射的子树开始遍历

const mapStateToProps = (state) {
    return {
        state.value
    }
}

如果您希望减少嵌套,还有一个Higher-Order Component

答案 1 :(得分:2)

我已经以不同的方式实现了它,而没有用命名空间实际更改动作名称。

相反,我添加了infra函数,它们将拦截动作创建者并为每个动作添加meta-data。 (关注FSA) 这样您就不需要更改减速器或mapStateToProps功能。

它也与redux-thunk兼容。

应该易于使用...... reducer-action-interceptor

答案 2 :(得分:0)

我将问题解释为:

  • 您的商店中有内容数据(例如,板块及其标题)
  • 您具有用于绘制数据位的组件(例如您的<SectionHeader />
  • 您想在页面上显示多个部分,但当前所有标题均具有相同的文字

一种可能的解决方案是,将“节”的概念添加到商店中。您将创建用于管理数据内容结构的化简器。例如。一次的存储状态可能看起来像这样:

{ 
  sections: {
     0: {
        header: 'My section title',
        content: 'Whatever your content is'
     },
     1: {
        header: 'My other section title',
        content: 'Loads of lovely writing or hrefs to images or whatever'
     }
  }
}

```

然后,您将拥有一个“容器组件”或“布局组件”或“智能组件”(它们有很多名称),“知道”您要在特定页面上使用第2节和第4节。如何知道这取决于您。也许您对索引进行了硬编码(因为它始终是相同的),也许您有一个过滤规则,也许您在商店中还有另一个字段定义了选择...等等。

然后,容器组件会将选定的标题传递到“哑巴”中,也许像这样:

<SectionHeader>{sections[2].header}</SectionHeader>

<SectionHeader title={sections[2].header} />

答案 3 :(得分:0)

将我们的组件转换为哑(无状态)组件,以便这些组件可以轻松重用而不会出现任何复杂情况。