8

Assume following structure

stores/
  RouterStore.js
  UserStore.js
  index.js

each of ...Store.js files is a mobx store class containing @observable and @action. index.js just exports all stores, so

import router from "./RouterStore";
import user from "./UserStore";

export default {
  user,
  router
};

What is correct way to access one store inside another? i.e. inside my UserStore, I need to dispatch action from RouterStore when users authentication changes.

I tired import store from "./index" inside UserStore and then using store.router.transitionTo("/dashboard") (transitionTo) is an action within RouterStore class.

But this doesn't seem to work correctly.

Ilja
  • 44,142
  • 92
  • 275
  • 498

3 Answers3

7

In this case you just need to pass only one link

Just create global store and pass link of the GlobalStore to every children stores where you need to get access:

// global parent store
class GlobalStore {
    constructor() {
        this.routerStore = new RouterStore(this);
        this.userStore = new UserStore(this);
        // ... another stores
    }
}

// access in child
class UserStore {
    constructor(rootStore) {
        this.routerStore = rootStore.routerStore;
    }

    // ...
}

// In root component:
<MobxProvider {...new GlobalStore()}>
  <App />
</MobxProvider>
zemil
  • 3,235
  • 2
  • 24
  • 33
6

Your propose solution doesn't work because you are interested in the instance of the store which contains the observed values instead of the Store class which has no state.

Given that you don't have any loop between store dependencies, you could pass one store as a constructor argument to another store.

Something like:

routerStore = new RouterStore(); 
userStore = new UserStore(routerStore); 

stores = {user: userStore, router: routerStore};

Here you pass the routerStore instance to the userStore, which means that it'll be available. For example:

class UserStore {
    routerStore; 
    constructor(router) {
        this.routerStore = router
    }; 

    handleLoggedIn = () => {
         this.routerStore.transitionTo("/dashboard") 
         // Here the router has an observable/actions/... set up when it's initialized. So we just call the action and it all works. 
    }
} 

Another way could be to pass the other store (say routerStore) as an argument when calling a function that is in userStore.

Christopher Chiche
  • 15,075
  • 9
  • 59
  • 98
  • Ah makes sense, first off should it be `userStore = new UserStore(routerStore)` ? And Secondly, within UserStore class do I just take in router in a normal constructor, or do I need to apply some mobx things to it, i.e make that store an observer or something? Any chance you could provide extended example? – Ilja Jul 05 '17 at 14:25
  • I fixed the typo. Thanks for noticing. – Christopher Chiche Jul 05 '17 at 14:26
  • You can use the UserStore as a normal constructor argument. You just share the instance of your store, you don't create a new store so there is no need to specify anything. I'll look for an example – Christopher Chiche Jul 05 '17 at 14:27
0

Look my solution with RootStore: here

  • 3
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 12 '22 at 20:34