score:18
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
score:1
initializing your rootstore directly in api.js file before passing it to provider is sometimes not what you want. this can make injecting the instance of main store class harder into other js files:
example 1:
app.js - creates new instance before passing it to provider:
//root store declaration
class rootstore {
constructor() {
...
}
}
const rootstore = new rootstore()
// provide the store to the children
<provider rootstore={rootstore}>
<app />
</provider>
example 2:
rootstore.js - creates new instance directly in rootstore class:
// root store declaration
class rootstore {
constructor() {
...
}
}
export default new rootstore();
example 1
compared to example 2
, makes harder to access/inject the store in another part of the application, like in api.js
described below.
api.js file represents axios wrapper (in my case it handles global loading indicator):
import rootstore from '../stores/rootstore'; //right rootstore is simply imported
const axios = require('axios');
const instance = axios.create({
...
});
// loading indicator
instance.interceptors.request.use(
(request) => {
rootstore.loadingrequests++;
return request;
},
(error) => {
rootstore.loadingrequests--;
return promise.reject(error);
}
)
and using react hooks, you can inject the store that way:
import { observer, inject } from "mobx-react";
const yourcomponent = ({yourstore}) => {
return (
...
)
}
export default inject('yourstore')(observer(yourcomponent));
score:14
i would recommend you to have multiple stores, to avoid chaining of stores. as we do in our application:
class rootstore {
@observable somepropusedinotherstores = 'hello';
}
class authstore {
@observeble user = 'viktor' ;
constructor(rootstore) {
this.rootstore = rootstore;
}
// this will reevaluate based on this.rootstore.somepropusedinotherstores cahnge
@computed get greeting() {
return `${this.rootstore.somepropusedinotherstores} ${this.user}`
}
}
const rootstore = new rootstore();
const stores = {
rootstore,
bankaccountstore: new bankaccountstore(rootstore),
authstore = new authstore(rootstore)
}
<provider {...stores}>
<app />
</provider>
in such a manner you can access exactly the store you need, as mostly one store covers one domain instance. still, both sub-stores are able to communicate to rootstore
. set its properties or call methods on it.
if you do not need a cross store communication - you may not need a rootstore
at all. remove it and don't pass to other stores. just keep 2 siblings stores
answering your question on injecting not a whole store, you may benefit from mapperfunction
(like mapstatetoprops
in redux) docs here
@inject(stores => ({
someprop: stores.rootstore.someprop
})
)
@observer
class user extends react.component {
// no props.rootstore here, only props.someprop
}
Source: stackoverflow.com
Related Query
- Correct way of Creating multiple stores with mobx and injecting it into to a Component - ReactJs
- React Convert Div and Table Component Into PDF With Multiple Pages and CSS
- Having difficulty with unit testing MobX observer components with multiple stores injected
- How to combine multiple stores as Root Store in Mobx and get access of in each other's fields and functions
- Correct way to use ref with Next.js for a Link and an <a>?
- How to make multiple HTTP requests with RxJS and merge the response into one payload and map it to another action?
- Correct way to React axios post with UUID and nested object in JSON payload?
- Better use some large or multiple small stores with React and Reflux
- What is the correct way to React Hook Fetch Api and store to Redux and retrieve it with Selector immediately?
- Creating a Redux Observable Epic with multiple API Calls - Passing the results of the first into the second
- React Reflux: Correct way to initiate stores and update dependent components
- Correct way to cancel eventListeners with nextjs, react and flowplayer
- Correct way to update state with react select multiple
- Is there a way to build multiple apps from single one with replacing some assets and components?
- Is there any way to turn a webpage that is styled partially with Javascript into pure HTML and CSS?
- Creating a work hours component - How to useState with multiple values going into an array
- Correct way to push into state array
- Multiple classNames with CSS Modules and React
- Is there any way to see names of 'fields' in React multiple state with React DevTools when using 'useState' hooks
- Proper way to navigate with React Native, Redux, and Navigator
- React i18next and correct way of changing language
- using mobx with react functional components and without decorators
- Correct way (if possible) to store JSX code into a Javascript variable
- Correct way to throttle HTTP calls based on state in redux and react
- React component with Edit Mode and View Mode, is this a correct pattern?
- Best way for internationalization with Gatsby and Strapi
- How is the correct way to have multiple dataProviders in react-admin?
- Multiple Registration Form with redux and react
- What is the correct way of dispatching an action not tied to a component with Redux?
- Reactjs - correct way of inherit props to first level children and nested children
More Query from same tag
- Rsuite TreePicker clear selections programmitacally - ReactJS
- React routing with Hapi
- Animations and first load are lags because of css @fontface
- Write proper css/styling for an image and a text next to it
- CodeSandbox with Material-UI error: undefined is not an object (evaluating '_context$muiTheme.borderRadius')
- How to set width of page in react js
- Do the constructors of React Components need the props argument?
- react-final-form state does not contains empty inputs
- Sequelize query to select match or partially match name
- best way to use .unshift in react to push variables in a state
- Why do I have to list my peerDependencies as externals in the webpack config when creating a package?
- How select checkbox in Reactjs?
- This expression is not callable. Not all constituents of type 'string | ((searchTerm: string) => Promise<void>) | []' are callable
- Passing props through nested Styled Components
- redux-promise use 'then()' after dispatching action
- ReduxForm - getting select value from Semantic-UI select input
- How to send formdata with other data in MERN App?
- Change the background of the Row containing the column headings in Table component of ANTD
- I want to display random images in background but the code is not working
- How to create new element and render data each time the data is fetched in react
- calling redux actions from leaflet map
- How to optimize my code with useMemo in React?
- React (w/ react-redux) caching options
- NextJS API not posting to external domains
- TypeScript: How to pass type information from parent to child?
- How do you animate menu with framer motion on-click?
- IndexRoute not working for "/"
- ERROR: Cannot define class using reflection
- How to write Superscript in ReactJS in navigation bar
- How to re-render a component on each of multiple state changes?