BaSic
BaSic

Reputation: 113

How to set up multiple providers with different stores?

I'm currently working on project and I'm facing a problem. I'd love to end with different react sub-apps with different providers and store.

I've been already trying to apply two separate stores, without success so far. The main problem is when i have one global store everything is working just fine, when i try to apply different stores to different routes app is just simply using only first of them. Problem is that the app will be working on vulnerable data i have to split it among multiple stores.

Global store works just fine among component, but when i try to separate them it's not working properly.

So, this one is working good.

const MainTemplateWithRouter = (
<div>
   <Router>
       <Provider store={createStore(reducers)}>
              <Switch>
                    <Route exact path="/" component={DashBoard} />
                    <Route path="/auth" component={Auth} />
                    <Route path="/admin-panel" component={AdminPanel} />
                    <Route path="/project-manager" component={ProjectManager} />
                    <Route path="/test" component={Test} />
                    <Route path="*"  component={NotFound} />
              </Switch>
       </Provider>
   </Router>
</div>
);

ReactDOM.render(MainTemplateWithRouter, document.querySelector('#root'));

Perfect solution would be something like that with one global store (to storing e.g. currently selected language (multi lang app)) and one store for each sub-app. As mentioned above. App will be huge with a lot of sub-apps that should be stored in different stores.

const MainTemplateWithRouter = (
<div>
   <Router>
           <h1>Header with Logo: XXXX</h1>
                <div>
                    <Link to="/">Home</Link>
                        <br/><br/>
                </div>

       <Provider store={createStore(reducers)}>
              <Switch>
                    <Route exact path="/" component={DashBoard} />
                    <Route path="/auth" component={Auth} />
                    <Provider store={createStore(adminPanelReducers)}>
                    <Route path="/admin-panel" component={AdminPanel} />
                    </Provider>
                    <Route path="/project-manager" component={ProjectManager} />
                    <Provider store={createStore(testReducer)}>
                    <Route path="/test" component={Test} />
                    </Provider>
                    <Route path="*"  component={NotFound} />
              </Switch>
       </Provider>
   </Router>
</div>
);

ReactDOM.render(MainTemplateWithRouter, document.querySelector('#root'));

What am I doing wrong? Is it possible to achieve one global stores and separate stores for each subapp? If not, can i store currently selected lang in global context and create store for each sub-app?

@Edit

https://redux.js.org/recipes/isolating-redux-sub-apps was the thing i needed.

Separated the stores among sub-apps according to the docs. However i can't use global store and local stores at the same time.

Upvotes: 6

Views: 11292

Answers (1)

Estus Flask
Estus Flask

Reputation: 222474

This React Redux section addresses only multiple sibling stores.

React Redux 6 was changed to use React context API instead of legacy Context. Redux Provider uses React context Provider to provide a state to connected components. It's natural for context API Provider to override the value provided by parent Provider, so only innermost Provider will be taken into account by connected component.

If there are multiple nested stores, they can have their own contexts that has to be specified in both Redux Provider and connect:

const GlobalContext = React.createContext();
const AdminContext = React.createContext();

...

   <Provider context={GlobalContext} store={globalStore}>
     ...
     <Provider context={AdminContext} store={adminStore}>
        <Route path="/admin-panel" component={AdminPanel} />
     </Provider>
      ...
   </Provider>

...

@connect(globalMapState, null, null, { context: GlobalContext })
@connect(adminMapState, null, null, { context: AdminContext })
class AdminPanel ...

Or sibling can use default Redux context to avoid boilerplate code:

const GlobalContext = React.createContext();

...

   <Provider context={GlobalContext} store={globalStore}>
     ...
     <Provider store={adminStore}>
        <Route path="/admin-panel" component={AdminPanel} />
     </Provider>
      ...
   </Provider>

...

@connect(globalMapState, null, null, { context: GlobalContext })
@connect(adminMapState)
class AdminPanel ...

Upvotes: 9

Related Questions