Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 381
Rahul Avatar asked Mar 20 '17 14:03

Rahul


People also ask

Can I pass multiple components within connect Redux?

Since you can have only one default export, you'd have to use named export in this case or split up those two components in two files.

Should I have multiple Redux stores?

Some valid reasons for using multiple stores in Redux might include: Solving a performance issue caused by too frequent updates of some part of the state, when confirmed by profiling the app.

Can Redux have multiple states?

Theoretically, there is only one global state. However, we can divide the management of the global state into multiple reducers which all have their own state. Let's take a look at how this can be achieved.

How do I use multiple stores in react-Redux?

Create a context for each store. You can also import ReactReduxContext from react-redux and use it for one of the stores, which you want to make default. Now wrap the root component of the react application with a provider for each store, passing the contexts as props.


1 Answers

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.

like image 127
Michael Peyper Avatar answered Sep 21 '22 15:09

Michael Peyper