react hook 风格下不再使用class类的形式定义组件,也就不再适用mobx以前版本的装饰器语法。
以下分享 reack hook 语法风格下使用 mobx v6 版本的状态管理配置使用方式。
相关依赖版本:
"react": "^17.0.2",
"mobx": "^6.3.2",
"mobx-react-lite": "^3.2.2",
mobx
是 react 生态中常用的状态管理插件之一,特点是配置及使用方式比较简便,方式上和 vuex 有些相似。
官方中文文档:https://zh.mobx.js.org/react-integration.html
mobx-react-lite
是配合 react 使用的一个轻量化插件,只支持函数式组件,适合 react hook。
官方已不建议使用装饰器语法,主要原因是js装饰器在现在的 ES 规范中并不成熟(目前在stage-2提案阶段且迟迟无法推进),而且引入装饰器语法也会增加打包后的代码体积。这里也将完全放弃装饰器方式。
以下配置使用 react context 方式来传递数据,这也是官方推荐的方式。因为直接引用store原始数据在有多个module模块下可能会使引用变得杂乱,管理维护困难且不利于单元测试。
先安装依赖:npm i -S mobx mobx-react-lite
创建 根store src/store/index.js
:
import User from './modules/user'
export default {
userStore: new User(),
}
创建 User模块 src/store/modules/user.js
import { makeAutoObservable } from 'mobx'
export default class User {
constructor () {
/**
* state
*/
this.ticket = '' // 登录凭证ticket
makeAutoObservable(this)
}
/**
* computed
*/
get isLogin () {
return !!this.ticket
}
/**
* action
*/
setTicket (val) {
this.ticket = val || ''
}
}
创建 store 状态管理的 context 文件 src/contexts/storeContext.js
:
import React from 'react'
import store from '@/store'
const storeContext = React.createContext(store)
export default storeContext
创建 store 状态管理的 hook 文件 src/hooks/storeHook.js
:
import { useContext } from 'react'
import StoreContext from '@/contexts/storeContext'
import { observer } from 'mobx-react-lite'
function useStore () {
const store = useContext(StoreContext)
return store
}
export {
observer,
useStore,
}
项目入口文件 src/index.js
里引用:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import StoreContext from '@/contexts/storeContext'
import store from '@/store'
ReactDOM.render(
<React.StrictMode>
<StoreContext.Provider value={store}>
<App />
</StoreContext.Provider>
</React.StrictMode>,
document.getElementById('root')
)
示例组件 src/App.jsx
:
import { useStore, observer } from '@/hooks/storeHook'
function App () {
const { userStore } = useStore()
function onSetStore () {
userStore.setTicket('ttt')
}
return (
<div>
<p>ticket:{userStore.ticket}</p>
<button onClick={onSetStore}>修改store中的ticket</button>
</div>
)
}
export default observer(App)
示例 js src/http/axios.js
:
import axios from 'axios'
import store from '@/store'
const { userStore } = store
const service = axios.create()
service.interceptors.request.use(
(config) => {
config.headers = {
...config.headers,
ticket: userStore.ticket,
}
return config
},
err => {
Promise.reject(err)
}
)
export default service
src/store/index.js
文件里直接取。通过这种方式配置后,状态管理的使用将变得简单高效,完美兼容 react hook 语法,和 ts 配合也不再有障碍。