【前端开发日常 - 7】简单粗暴,在React中快速使用Mobx

需求背景

最近在做 React 项目,是一个简单的编辑页,刚开始没有考虑到复杂的场景,随着新的想法加入,现在需要增加多个页面,因此使用了 react-router ,为了在每个页面之间共享数据,实现状态管理,决定在项目中加入 Mobx 。

解决方案

1、安装 mobx 和 mobx-react ;
2、创建 store 并且使用 ;
3、使用@装饰器,在 【前端开发日常 - 3】让create-react-app支持@装饰器语法 文章中有介绍。

安装mobx

1
$ yarn add mobx mobx-react

创建 store

src 目录下增加一个 store 文件夹, 创建一个 index.js 文件,用来导出所有的 store , 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/store/index.js

import HomeStore from "./homeStore";
import UserStore from "./userStore";
import ArticleStore from "./articleStore";
let homeStore = new HomeStore();
let userStore = new UserStore();
let articleStore = new ArticleStore();
const stores = {
homeStore, userStore, articleStore
};
// 默认导出
export default stores;

关于 store 的创建,有以下几个部分:
1、在 mobx 引入 observableaction ,导出一个 class
2、使用装饰器, 用 @observable 定义变量 , 使用 @action 定义方法来修改变量。
articleStore 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// src/store/articleStore.js

import { observable, action } from "mobx";

import { ApiService } from "../services";

class ArticleStore {
@observable articleList = [];

@observable articlePage = 1;
articlePageSize = 10;
@observable articleCount = 0;

@action async getArticleList(page = 1) {
this.articlePage = page;
const data = {
page: this.articlePage,
pageSize: this.articlePageSize
}
const result = await ApiService.getArticleList(data);
if (result && result.success) {
this.articleList = result.data.list;
this.articleCount = result.data.count;
}
}
}
export default ArticleStore;

使用 store

store 创建好了之后,就是在入口部分使用,需要从 mobx-react 引入 Provider ,代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
// ...
import { Provider } from "mobx-react";
import stores from "./store";
// ...
function App() {
return (
<Provider {...stores}>
<div className="App">
<Router><RouterPage /></Router>
</div>
</Provider>
);
}

export default App;

引入 Providerstore ,从而创建一个数据的容器,子组件放在容器中实现跨组件数据共享, 类似于 react 的 context
然后,在需要的地方使用 store ,从 mobx-react 引入 observerinject , 使用装饰器,之后从组件的 props 上取值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import React, { Component } from 'react';
import { observer, inject } from "mobx-react";

import Article from './Article.jsx';

@inject("articleStore")
@observer
class ArticleList extends Component {
constructor(props) {
super(props);
}

async componentDidMount() {
this.getPage();
}

getPage = async (page = 1) => {
const { articleStore } = this.props;
await articleStore.getArticleList(page);
}

render() {

const { articleStore: { articleList } } = this.props;
return (
<div>
{
articleList.map((item, index) => <Article key={item._id} data={item} />)
}
</div>
)
}
}

export default ArticleList;

@observer 将组件变成响应式组件,数据改变时候可以重新渲染。
@inject("articleStore") 将数据注册到组件,可以在 props 取到。