Original Address: https://acme.top/mobx-react-stores-doc
Foreword
mobx-react-stores in order to facilitate antd pro developed using mobx, which codes a large number of ideas and with reference to the realization and umi of dva
installation
npm i mobx-react-stores
use
Gets stores
instance of an object
import {stores} from 'mobx-react-stores';
State Management
mobx-react-stores can be used as state management, but also its core purpose, interface design is relatively simple, mainly on two:
- stores.add (Model: Object | Promise, namespaceAlias: null | String) - used to
stores
inject to be managedmodel
objects
- Parameter
model
if an object must contain a string of typenamespace
attribute, which is used as astores
unique identifier, which is thestores
name of the attribute - Parameter
model
may be aPromise
target,Promise
you must return a string typenamespace
attribute - Parameters
namespaceAlias
Optionally, used tomodel
aliases, if presentmodel
may not containnamespace
properties
- dispatch ({type, payload}) - similar
dva
todispatch
, through fornamespace/action
quick access to this typemodel
functions in an object
- The parameter
type
is a string type, the formatnamespace/action
- Parameters
payload
of any type, optionally, used to pass parameters to the called function innamespace/action
the parameter is a function of the receivedpayload
dispatch
Generally injected directly into the context, to facilitate assembly call
Monitor the loading state
mobx-loading
Dva-loading can achieve a similar effect, and the model easy to monitor the execution state of the action, to reduce the component developers show
hide
operate
- Get loadingStore object's methods
import {loadingStore} from 'mobx-loading'
mobx-react-stores default integrated mobx-loading, as a built-in attribute stores, for the namespace loading
, the objects may be obtained directly from the stores in loadingStore
const {loading} = stores;
- Use
// 通过 actions 获取指定 namespace/action 的当前加载状态
loading.actions['goods/fetchList']
// 通过 models 获取指定 namespace 的当前加载状态
// namespace 下任何 action 加载状态为 true,则此 namespace 的加载状态即为 true
loading.models.goods
// 通过 global 获取全局的加载状态
// 只要任何一个 model 的状态为 true,则 global 的状态即为 true
loading.global
// 从 mobx-react-stores 和 mobx-loading 中都可以获取 namespace 装饰器
// 用作 class,方便向 class 中注入 namespace 属性
import {namespace} from 'mobx-loading';
import {namespace} from 'mobx-react-stores';
- Examples of Use
// 获取 namespace 和 loading 装饰器
import {namespace, loading} from 'mobx-react-stores';
import {fetchRandomUser} from "@/services/demo";
// 默认会为 class 添加 namespace 属性,值为将 class 类名转换为首字母小写的字符串
// 此处 namespace 值为 randomUser
@namespace
class RandomUser {
user;
message;
// 通过 loading 装饰器,向 loadingStore 中注入当前 action 的加载状态
@loading
fetchUser = async () => {
this.user = null;
this.message = null;
const response = await fetchRandomUser().catch(this.onRejected);
if (response.results) {
const user = response.results[0];
this.change({
user: {
name: `${user.name.first} ${user.name.last}`,
email: user.email,
picture: user.picture.large
},
message: null
});
}
}
change = ({user, message}) => {
this.user = user;
this.message = message;
}
onRejected = (e) => {
return {
status: 500,
message: e.message
}
}
}
export default new RandomUser();
// -----------------------RandomUser.js--------------------------------
import React from 'react';
import {inject} from 'mobx-react'
@inject(({stores: {dispatch, loading, randomUser}}) => {
return {
dispatch,
randomUser,
loading: loading.models.randomUser
}
})
class RandomUser extends React.PureComponent {
onFetchUser = () => {
const {dispatch} = this.props;
dispatch({
type: 'randomUser/fetchUser'
})
}
render() {
const {loading, randomUser} = this.props;
if (loading) {
// do someting
}else{
const {user, message} = randomUser;
// do someting
}
}
}
export default RandomUser;
@loading (names: String | Array | null) - loading acting on the decorative function in the model, and may receive an array of strings parameters
For example: @loading ( 'randomUser / fetchList'), @ namespace ([ 'randomUser', 'fetchList']) with the results of the above sample code as
loading
Decorator preferably used class name of the current namespace attribute and the function (first letter lowercase) generated uniquely identifies the action, without the namespace attribute class name (first letter lowercase) use. No reference example loading door is a function of the load state may beloadingStore.actions['randomUser/fetchList']
achieved
The above example is loading decorators, and stores.loading different. stores.loading is injected property after stores loadingStore
Routing Management
In order to facilitate management and routing injection model in the stores, mobx-react-stores offer similar umi management routing method, but not as to generate temporary files like umi, but a more direct way
Suggested
src
the new catalogdefault.router.js
file to store the route, if the module number and complexity of the routing can be dispersed to each module to the file is then polymerized
Routing Example
export default [
// user
{
path: '/user',
// 布局文件
component: () => import('./layouts/UserLayout'),
LoadingComponent = require('./components/PageLoading').default,
Routes: [require('./pages/Authorized').default],
authority: ['admin', 'user'],
routes: [
// 从 /user 重定向到 /user/login
{path: '/user', redirect: '/user/login'},
{path: '/user/login', name: 'login', component: () => import('./pages/User/Login')},
{
name: 'register',
path: '/user/register',
models: () => [import('./pages/User/models/register')],
component: () => import('./pages/User/Register')
},
{
name: 'register.result',
path: '/user/register-result',
component: () => import('./pages/User/RegisterResult'),
},
],
}
]
- name - the name of the route, will generate a menu for the Build menu, name and path of ~ Antd Pro there are so defined
- path - the path routing
- Models - Model collection of objects, supports demand loading, loaded together with the component, support:
() => [import('xxx/model1'), import('xxx/model2')]
,() => import('xxx/model1')
,[() => import('xxx/model1'), () => import('xxx/model2')]
and other forms. The main sub facilitate routing of models and an array of superior routing models were merged, some of the common models can be placed in higher-level routing, ease of management. - the Component - component, if there are lower-level routing, it is the lower routing layout files, supports asynchronous demand loading (must provide a function like this:
()=>import('xxxx'))
- LoadingComponent - load performance component when the asynchronous demand loading assembly
- The Routes - easy to customize permissions check routing, refer to Antd Pro to achieve
- Authority - required permissions to access routes, for permission to check, refer to Antd Pro to achieve
- routes - sub-route set
Use routing
import {formatterRoutes, renderRoutes} from 'mobx-react-stores';
import router from './default.router.js';
// ... do someting
// 格式化
const routes = formatterRoutes(this.router, this.stores);
// 渲染路由
let children = renderRoutes(routes);
return (
<Router history={history}>
{children}
</Router>
);
// ... do someting
globalization
mobx-react-stores recommended react-intl managing international
Injection Locale
import {stores, Locale} from 'mobx-react-stores';
// ... do someting
// 可参考 Antd Pro
const translations = {
'en-US': {
messages: {
...require('../locales/en-US.js').default,
},
locale: 'en-US',
antd: require('antd/lib/locale-provider/en_US'),
data: require('react-intl/locale-data/en'),
momentLocale: '',
},
'zh-CN': {
messages: {
...require('../locales/zh-CN.js').default,
},
locale: 'zh-CN',
antd: require('antd/lib/locale-provider/zh_CN'),
data: require('react-intl/locale-data/zh'),
momentLocale: 'zh-cn',
},
// ... 其他语言包
};
// 注入
stores.add(new Locale('zh-CN', translations));
// ... do someting
Switch language
stores.locale.change('zh-CN');
// 或者
dispatch({
type: 'locale/change',
payload: 'zh-CN'
});
integrated
To simplify development, facilitate the use of international, history, etc., mobx-react-stores provides an integrated interface to good
Examples of Use
In the src
directory new index.js
file as a file entry
// 兼容 IE9、IE10 ~ 如果需要的话请解开封印
// import 'react-app-polyfill/ie9';
// import 'react-app-polyfill/stable';
import React from 'react';
import {LocaleProvider} from 'antd';
import {app} from 'mobx-react-stores';
import get from 'lodash/get';
import './utils/axios'; // 初始化拦截器
import './global.less';
import * as serviceWorker from './serviceWorker';
app.stores = require('./models').default;
app.router = require('./default.router').default;
app.defaultLoadingComponent = require('./components/PageLoading').default;
// 渲染时回调,方便一些额外的操作,比如注入 antd 的国际化
app.renderCallback = (children) => {
const {locale} = app.stores;
const antd = get(app.stores, 'locale.translation.antd', undefined);
if (antd) {
return (
<LocaleProvider locale={antd.default || antd}>
{children}
</LocaleProvider>
);
}
return children;
};
app.render(document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
After integration
- stores will be obtained
intl
,routing
two objects, and operations may be used to route international - intl is an example of an object after the react-intl injection, may be used
intl.formatMessage()
and other functions - routing may be implemented
routing.push()
,routing.replace()
like routing operations