用法: 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
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);
// 其實是對間接引用(dereference)值的反應,值須要經過引用來傳遞而不是經過(字面量)值來傳遞。
// React.render(<Timer timerData={timerData.secondsPassed} />, document.body) 將不會改變@observer
// 使用 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 調用後會觸發此鉤子