9 项目中使用mobx进行状态管理
mobx有以下几个概念:observable,action,reaction,observer。
MobX 支持单向数据流,也就是动作改变状态,而状态的改变会更新所有受影响的视图。
Observable 存放状态
const appState = observable({
name: '麦乐',
height: '168cm'
})
Actions 更新state
主要用来更新状态的,需要把更新状态的函数传入action()函数中,action()函数会返回一个新的函数 。
appState.resetTimer = action(function reset() {
appState.name = 高秀;
});
Provider 挂载store
import { store } from './appStore'
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'mobx-react'
ReactDOM.render(
<Provider store={store}>
<App />
<Provider>, document.getElementById('root')
)
Inject函数注入store
import { inject, observer } from 'mobx-react'
@inject('store')
@observer
class App extends React.Compnent {
render() {
const { store } = this.props
}
}
Observer 观察数据改变 重新渲染
observer()会自动跟踪render方法里面消费的那些observable state。只要其中任何的observable发生了改变,re-render就会发生。
扫描二维码关注公众号,回复:
6650185 查看本文章
先来解决一下装饰器问题
VS CODE对装饰器报错
文件 > 首选项 > 设置(ctrl + ,) 勾选一下就可以了
搜索experimentalDecorators,设置"javascript.implicitProjectConfig.experimentalDecorators": true
,该选项默认为false,需要改为true
npm install --save @babel/plugin-proposal-decorators
// package.json文件下面的babel选项中加入plugin属性
"babel": {
"presets": [
"react-app"
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
},
// appStore.js
import { observable, action, runInAction, flow } from 'mobx'
import Axios from '../utils/request'
// observable就是封装了state
// const appStore = observable({
// counter: 0
// })
// Actions 就是用来更新state的
// appStore.addCount = action(()=>{
// appStore.counter += 1
// })
// appStore.subCount = action(()=>{
// if (appStore.counter <= 0) return;
// appStore.counter -= 1
// })
// use decorator packaging class
class appStore {
// 存放状态
@observable itemList = ['3']
@observable counter = 0
// action函数
@action
addCount() {
this.counter +=1
}
@action
addItem(item) {
if (this.itemList.indexOf(item) !== -1) return;
this.itemList.push(item)
}
// 把class实例提前绑定在该方法
@action.bound
removeItem(item) {
this.itemLis = this.itemList.filter((x, index)=>{
return x !== item;
})
}
// 异步数据请求
@action.bound
async query() {
try {
this.status = 'pending'
const result = await Axios.get('/h5/misc/config')
runInAction(() => {
this.itemList = result.List
this.counter = result.counter
})
} catch (e) {
runInAction(() => this.status = 'failed')
console.log(e)
}
}
// <- note the star, this a generator function!
// 多个数据请求
@action.bound
loadEquity = flow(function* () {
// yield instead of await
try {
const account = yield Axios.get('/h5/misc/config')
const summary = yield Axios.get('/h5/misc/config')
const equityList = yield Axios.get('/h5/misc/config')
// the asynchronous blocks will automatically be wrapped in actions and can modify state
this.accountId = account.accountId
this.balance = account.balance
this.summary = summary
this.cardData = equityList
} catch (e) {
this.rpcError = true
}
})
}
export default new appStore();
// 根目录下的index.js 也就是入口文件 挂载storre
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import './index.scss'
// 把store传递到子孙组件中, 这样就可以在组件中直接inject()
import {Provider} from 'mobx-react'
import AppStore from './mobx/appStore'
ReactDOM.render(
<Provider store={AppStore}>
<App />
</Provider>,
document.getElementById('root'));
// +++++ 加入+++++
if (module.hot) {
module.hot.decline('./App');
}
// 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();
// Home下面的 index.js文件
import React from 'react';
import logo from '../../logo.svg';
import './index.scss';
import Footer from "../../publicComponents/Footer"
import Axios from "../../utils/request";
import { observer, inject } from "mobx-react"
/***
* 有了observable来代表state,有了action来修改state,
* 那么UI怎么消费state,并且响应state的变化呢。在react应用中,需要引入npm包mobx-react。
* 它提供一个observer()方法来绑定react和mobx。observer()包裹一个react component从而生成一个高阶component(HoC)来自动响应observable state的改变。
* observer()会自动跟踪render方法里面消费的那些observable state。
* 只要其中任何的observable发生了改变,re-render就会发生。
*/
// 使store跟component链接起来 注入store
@inject('store')
// 装饰器decorator来封装component
@observer
class Home extends React.Component {
constructor(props) {
super(props)
this.addCount = this.addCount.bind(this)
}
componentDidMount () {
Axios.get('/h5/misc/config').then((response) => {
console.log(response);
}).catch((err) => {
console.log(err)
})
}
addCount() {
const { store } = this.props
store.addCount()
}
render() {
const { store } = this.props
return (
<div className="Home">
<header className="Home-header">
<img src={logo} className="Home-logo" alt="logo" />
<p onClick={this.addCount}>{store.counter}</p>
<a
className="Home-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn ss
</a>
</header>
<Footer History={this.props.history} selectedTab='blueTab' />
</div>
);
}
}
export default Home;