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
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 inAuthStore
is changed. UseComputed
. This approach is common for both the above approachesAuthStore.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