Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way of Creating multiple stores with mobx and injecting it into to a Component - ReactJs

As suggested here in the Mobx documentation I have created multiple stores in the following manner:

class bankAccountStore {
  constructor(rootStore){
    this.rootStore = rootStore;
  }
...

class authStore {
  constructor(rootStore){
    this.rootStore = rootStore;
  }
...

And finally creating a root store in the following manner. Also I prefer to construct children stores within master's store constructor. Moreover, I found that sometimes my child store has to observe some data from parent store, so I pass this into child constructors

class RootStore {
  constructor() {
    this.bankAccountStore = new bankAccountStore(this);
    this.authStore = new authStore(this);
  }
}

Providing to the App in following manner:

<Provider rootStore={new RootStore()}>
  <App />
</Provider>

And injecting to the component in like this:

@inject('rootStore') 
@observer
class User extends React.Component{
  constructor(props) {
    super(props);
    //Accessing the individual store with the help of root store
    this.authStore = this.props.rootStore.authStore;
  }
}

Is it the correct and efficient way to inject the root store everytime to the component even if it needs a part of the root store? If not how to inject auth Store to the user component?

EDIT: I have made an answer concluding the github discussion. Link of the discussion provided in the answer

like image 735
uneet7 Avatar asked Jan 27 '19 22:01

uneet7


People also ask

How do you implement MobX in react?

Create a new React app We can use cd mobx-react to go into the folder. Now, inside of the src folder, we can create a folder for our components, create a PetList component inside the folder, and open the file in your favorite editor.

What is inject and observer in MobX?

My understanding is I that with observer , a change in all accessed observables in the last render will cause a re-render, even if the observable is nested deep in the data store, while inject only re-renders when observables accessed in the injector function change.

Does MobX work with functional components?

In this tutorial, we will learn how to use MobX with React Functional Components. MobX being a very useful state management library reduces the code that needs to be written for global state management. Mobx is easy to use and quick to learn.


1 Answers

This answer may be opinionated but it may help the community indirectly.
After a lot of research, I saw below approaches used in practice by many. General methods Have a root store that can act as a communication channel between stores.

Question 1: How to organise stores and inject them into the component?

Approach 1:

App.js

// Root Store Declaration
class RootStore {
    constructor() {
      this.userStore = new UserStore(this);
      this.authStore = new AuthStore(this);
    }
}    
const rootStore = new RootStore()

// Provide the store to the children
<Provider 
    rootStore={rootStore}
    userStore={rootStore.userStore}
    authStore={rootStore.authStore}
>
  <App />
</Provider>

Component.js

// Injecting into the component and using it as shown below
@inject('authStore', 'userStore')
@observer
class User extends React.Component {
    // only this.props.userStore.userVariable
}

Approach 2:

App.js

class RootStore {
    constructor() {
      this.userStore = new UserStore(this);
      this.authStore = new AuthStore(this);
    }
} 
const rootStore = new RootStore()

<Provider rootStore={rootStore}>
  <App />
</Provider>

Component.js

// Injecting into the component and using it as shown below
@inject(stores => ({
    userStore: stores.userStore,
    authStore: stores.authStore,
    })
)
@observer
class User extends React.Component {
    // no this.props.rootStore.userStore,userVariable here, 
    // only this.props.userStore.userVariable
}

Approach 1 and Approach 2 doesn't make any difference other than syntax difference. Okay! that is the injection part!

Question 2: How to have an inter-store communication? (Try to avoid it)

Now I know a good design keeps stores independent and less coupled. But somehow consider a scenario where I want the variable in UserStore to change if a certain variable in AuthStore is changed. Use Computed. This approach is common for both the above approaches

AuthStore.js

export class AuthStore {    
    constructor(rootStore) {
        this.rootStore = rootStore
        @computed get dependentVariable() {
          return this.rootStore.userStore.changeableUserVariable;                                      
        }
    }
}

I hope this helps the community. For more detailed discussion you can refer to the issue raised by me on Github

like image 158
uneet7 Avatar answered Oct 02 '22 00:10

uneet7