首页 文章

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

提问于
浏览
27

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

我们正在使用React-Redux

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

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

Problem details:

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

它侦听header属性reducer SectionheaderReducer .

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

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

3 回答

  • 0

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

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

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

    Disclaimer: 我是以下图书馆的主要撰稿人 .

    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 .

  • 2

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

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

    它也与 redux-thunk 兼容 .

    应该很容易使用... reducer-action-interceptor

  • 31

    我将这个问题解释为:

    • 您在商店中有内容数据(例如章节及其 Headers )

    • 你有用于绘制数据位的组件(例如你的 <SectionHeader />

    • 您希望在页面上显示多个部分,但目前所有 Headers 都具有相同的文本

    一种可能的解决方案是让您将“部分”的概念添加到您的商店 . 您将创建用于管理数据内容结构的Reducer . 例如 . 商店状态,有时可能如下所示:

    { 
      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部分 . 怎么知道这一点,取决于你 . 也许你对索引进行硬编码(因为它总是相同的),也许你有一个过滤规则,也许你在商店里有另一个定义选择的字段......等等 . 
    
    然后容器组件将所选的 Headers 传递给“哑”,可能是这样的:
    
    ```java
    <SectionHeader>{sections[2].header}</SectionHeader>
    

    要么

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

相关问题