Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
294 views
in Technique[技术] by (71.8m points)

javascript - having multiple instance of same reusable redux react components on the same page/route

We are creating a large front-end application.

We are using React-Redux for it

We are creating some reusable components.

This question is regarding having multiple instance of same reusable redux react components on the same page/route

Problem details:

We have a Sectionheader component. Which is bound to redux state.

It listens to the header property reducer SectionheaderReducer.

As we have 2 instances of this Sectionheader on the page both tend to show same values as they are bound to the same store state-property.

How to make the redux based reusable react component configurable? So that each instance can have different value of header property for reducer SectionheaderReducer

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to implement some way of namespacing the instances. This can be as basic as passing in a key to differentiate the components and reducers.

You can use the ownProps in your mapStateToProps function to guide the mapping to a namespace

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

The same method can be used to pass on a namespace to the mapDispatchToProps

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

Just remember to use the namespace in the action type so the reducers don't tread on toes

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

And make sure the reducer is namespaced too

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

Now add the 2 namespaced reducers when combining reducers

combineReducers({
    myInstance1 : myReducer('myInstance1')
    myInstance2 : myReducer('myInstance2')
}

Finally pass the namespace to each instance

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

Disclaimer: I am the main contributor on the following library.

redux-subspace can provide a more advanced namespacing implementation without you having to reimplement this pattern for every component you want to have multiple instances for.

Creating the reducers is similar to above

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

Then SubspaceProvider can be used to switch out the state for each component

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

Just ensure you also change your mapStateToProps function to so start traversing from the subtree mapped in the provider

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

There is also a Higher-Order Component if you prefer to reduce nesting.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...