前期准备
使用 react-app-rewired 修改 create-react-app 的配置, 使其支持装饰器语法
- 安装依赖
yarn add react-app-rewired
yarn add --dev customize-cra
yarn add @babel/plugin-proposal-decorators
- config-overrides.js
const {
override,
addDecoratorsLegacy,
disableEsLint
} = require('custommize-cra');
module.exports = override(
addDecoratorsLegacy(),
disableEsLint()
);
- package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
}
- 处理 vscode 报错
"javascript.implicitProjectConfig.experimentalDecorators": true
安装 mobx
yarn add mobx
yarn add mobx-react
创建 store
import {observable, action, computed} from 'mobx';
const INIT_TODO = {
id: 1,
text: 'mobx事例',
completed: false
}
class TodoStore {
@observable
todoList = [INIT_TODO];
@computed
get totalTodos() {
return this.todoList.length
}
@action
addTodo(text){
const newTodo = {
id: +new Date(),
text,
completed: false
}
this.todoList = [...this.todoList, newTodo];
}
@action
changeStatus(id) {
this.todoList = this.todoList.map(item => {
return item.id === id
? {...item, completed: !item.completed}
: item
})
}
@action
delTodo(id){
this.todoList = this.todoList.filter(item => item.id !== id)
}
@action
clearTodos() {
this.todoList = [];
}
}
export default TodoStore;
Provider 提供容器
import {Provider} from 'mobx-react';
import stores from './store';
<Provider {...stores} >
<div className="App">
<Input
value={value}
placeholder="添加代办"
onPressEnter={handleSubmit}
onChange={e => setValue(e.target.value)}
/>
<TodoList />
<Footer />
</div>
</Provider>
在类组件中使用
import {inject, observer} from 'mobx-react';
import React,{PureComponent} from 'react';
import Item from './item';
@inject('todoStore')
@inject('globalStore')
@observer
class TodoList extends PureComponent {
handleDel = (id) => {
this.props.todoStore.delTodo(id);
}
render() {
const {todoStore: {todoList, totalTodos}} = this.props;
return (
<div>
{
totalTodos
? <>
{
todoList.map(item => (
<Item key={item.id} data={item}/>
))
}
</>
: <div className="empty">今日事今日毕</div>
}
</div>
)
}
}
export default TodoList;
在函数组件中使用
import { inject, observer } from 'mobx-react';
import React from 'react';
function Item({todoStore, data}) {
return (
<div >
<p>
<span>
{data.text}
</span>
<span>
<span
className="pointer"
onClick={_ => todoStore.delTodo(data.id)}
>
删除
</span>
</span>
</p>
</div>
)
}
export default inject('todoStore','globalStore')(observer(Item));
结合 hooks 使用
- 安装 mobx-react-lite
yarn add mobx-react-lite
- 创建 context
import React from 'react';
import stores from '../store';
export const StoresContext = React.createContext({
...stores
})
- 创建 context hooks
import React from 'react'
import { StoresContext } from '../contexts';
export const useStores = () => React.useContext(StoresContext)
- 在组件中使用
import React from 'react';
import { useStores } from '../hooks';
import { useObserver } from 'mobx-react-lite';
function Footer() {
let store = useStores();
const {todoStore} = store;
return useObserver(() => (
<div className="footer">
count: {todoStore.totalTodos}
<span className="pointer" onClick={_ => todoStore.clearTodos()} >重置</span>
</div>
))
}
export default Footer;