Flow
用法: flow(function* (args) { })
// 包装异步函数。这将确保所有回调都会被 action() 包装。
// flow() 接收 generator 函数作为它唯一的输入
// flow 会返回一个 promise ,需要的话可以使用 cancel() 进行撤销。
import { configure } from 'mobx';
// 不允许在动作外部修改状态
configure({ enforceActions: true });
class Store {
@observable githubProjects = [];
@observable state = "pending"; // "pending" / "done" / "error"
fetchProjects = flow(function* fetchProjects() { // <- 注意*号,这是生成器函数!
this.githubProjects = [];
this.state = "pending";
try {
const projects = yield fetchGithubProjectsSomehow(); // 用 yield 代替 await
const filteredProjects = somePreprocessing(projects);
// 异步代码自动会被 `action` 包装
this.state = "done";
this.githubProjects = filteredProjects;
} catch (error) {
this.state = "error";
}
})
}
// Flows 是可以取消的,调用返回的 promise 的 cancel() 方法。
// 会立即停止 generator ,但是 finally 子句仍会被处理。
// 返回的 promise 本身会使用 FLOW_CANCELLED 进行 reject
// Flows 支持异步迭代器
async function* someNumbers() {
yield Promise.resolve(1)
yield Promise.resolve(2)
yield Promise.resolve(3)
}
const count = mobx.flow(async function*() {
// 使用 await 来循环异步迭代器
for await (const number of someNumbers()) {
total += number
}
return total
})
const res = await count() // 6
Reactions(反应) & Derivations(衍生)
observer
// observer 函数/装饰器可以用来将 React 组件转变成响应式组件
// 它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。
// observer 是由单独的 mobx-react 包提供的。
import {observer} from "mobx-react";
var timerData = observable({
secondsPassed: 0
});
setInterval(() => {
timerData.secondsPassed++;
}, 1000);
@observer class Timer extends React.Component {
render() {
return (<span>Seconds passed: { this.props.timerData.secondsPassed } </span> )
}
};
ReactDOM.render(<Timer timerData={timerData} />, document.body);
// @observer
实际上是对间接引用(dereference)值的反应,值需要通过引用来传递而不是通过(字面量)值来传递。
// React.render(<Timer timerData={timerData.secondsPassed} />, document.body) 将不会改变
// 使用 inject 将组件连接到提供的 stores
// 传递stores名称列表给 inject,这使得 stores 可以作为组件的 props 使用
// 应该一直使用 inject(stores)(component) 或 @inject(stores) class Component...。
// 直接传递 store 名称给 observer 的方式已废弃。
const colors = observable({
foreground: '#000',
background: '#fff'
});
const App = () =>
<Provider colors={colors}>
<app stuff... />
</Provider>;
const Button = inject("colors")(observer(({ colors, label, onClick }) =>
<button style={{
color: colors.foreground,
backgroundColor: colors.background
}}
onClick={onClick}
>{label}</button>
));
// 稍后..
colors.foreground = 'blue';
// 所有button都会更新
componentWillReact (生命周期钩子)
// React 组件通常在新的堆栈上渲染,这使得通常很难弄清楚是什么导致组件的重新渲染
// 当组件观察的数据发生了改变,会重新渲染,componentWillReact 会被触发。这使得它很容易追溯渲染并找到导致渲染的操作(action)。
import {observer} from "mobx-react";
@observer class TodoView extends React.Component {
componentWillReact() {
console.log("I will re-render, since the todo has changed!");
}
render() {
return <div>this.props.todo.title</div>;
}
}
1, componentWillReact 不接收参数
2, componentWillReact 初始化渲染前不会触发 (使用 componentWillMount 替代)
3, componentWillReact 对于 mobx-react@4+, 当接收新的 props 时并在 setState 调用后会触发此钩子