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

Rah*_*hul 31 redux

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

我们正在使用React-Redux

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

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

问题详情:

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

它侦听header属性reducer SectionheaderReducer.

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

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

Mic*_*per 40

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

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

const mapStateToProps = (state, ownProps) {
    let myState = state[ownProps.namespace]
    return {
        myState.value
    }
}
Run Code Online (Sandbox Code Playgroud)

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

const mapDispatchToProps = (dispatch, ownProps) {
    return {
        myAction: (myParam) => dispatch(myAction(ownProps.namespace, myParam))
    }
}
Run Code Online (Sandbox Code Playgroud)

只记得在动作类型中使用命名空间,这样减速器就不会踩到脚趾

const myAction => (namespace, myParam) {
    return { type: `${namespace}/${MY_TYPE_CONSTANT}`, myParam }
}
Run Code Online (Sandbox Code Playgroud)

并确保reducer也是命名空间

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

现在在组合reducers时添加2个名称空间缩减器

combineReducers({
    myInstance1 : myReducer('myInstance1')
    myInstance2 : myReducer('myInstance2')
}
Run Code Online (Sandbox Code Playgroud)

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

render() {
    return (
        <div>
            <MyComponent namespace='myInstance1' />
            <MyComponent namespace='myInstance2' />
        </div>
    )
}
Run Code Online (Sandbox Code Playgroud)

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

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

创建reducer与上面类似

const reducer = combineReducers({ 
    myInstance1: namespaced('myInstance1')(myReducer)
    myInstance2: namespaced('myInstance2')(myReducer)
})
Run Code Online (Sandbox Code Playgroud)

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

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

只需确保您也将mapStateToProps功能更改为开始从提供程序中映射的子树开始遍历

const mapStateToProps = (state) {
    return {
        state.value
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您希望减少嵌套,还有一个高阶组件.

  • 这个答案......就是为什么我永远不会使用Redux或任何这些单例模式.完全违背软件开发的概念需要做这种事情来支持两个实例.这通常在Vue,React State,Angular(2/4 +),聚合物和网络组件中得到解决.然而,React社区继续推动Redux没有明显的理由. (2认同)
  • @MichaelPeyper如果您有N个实例,N可以并且将由API调用更改并确定该怎么办?在这种情况下,我不确定我将拥有多少个组件实例.任何想法如何处理这种情况?目前,我使用本地状态的组件工作正常. (2认同)
  • 对于现在遇到此问题的任何人,作为对 @coding 评论的回应:这是正确的,redux singleton 模式不是很可重用,但这不是它要解决的问题。当您希望树中任何位置的组件修改/使用相同的数据而不传递大量的 props 和回调时(即当您想要单例/全局时),Redux 非常有用。当您需要渲染一个组件的 N 个副本且所有组件的行为方式都相同时,内部组件状态是更好的方法。当您需要(例如)同一个减速器的 3 个副本时,这个答案是一个折衷的办法。 (2认同)