React + MobX - 完全上手指南
前言
之前在學習 react 的狀態管理時當然第一個學到的就是 redux,關於 redux 如果有興趣或是還不清楚,可以先去看看 淺析 React Redux 的概念以及使用。而本篇的主角是 MobX,這篇會介紹關於 MobX 的一些概念以及基本用法,當然也會講到跟 redux 的區別,包括優勢選型等比較。
正文
MobX 其實跟 redux 一樣也是一個用於做全局狀態管理的一個工具,不過經過下面的介紹你就會發現 MobX 比 redux 方便簡單很多,所以其實 MobX 也蠻流行的。我會在介紹完 MobX 後再統一說說跟 redux 的對比。下面一樣以 todo 應用作為場景說說 MobX 的實現,廢話不多說進入 MobX 吧~
MobX 準備工作
首先,要在 react 應用中使用 MobX 我們當然要先裝 MobX 的包:
// npm
npm install mobx mobx-react
// yarn
yarn add mobx mobx-react
MobX 基本使用
其實 MobX 的概念很簡單,首先當然還是先要設計我們 todo 的 store。我們當然也是先建一個 store 文件夾存放狀態管理相關的所有代碼。
Store + Action
如果對 redux 有了解的人會知道,在 redux 中,redux 只有一個統一的大的 store,而具體怎麼處理,是根據你分發的 action 中的 type
進行不同的 reducer 處理,然後返回新的 state。
不過在 MobX 不是這樣的。MobX 不是單一數據源,在 MobX 可以有多個 store,我們可以根據不同的業務將狀態分成各自的 store,其實在某種意義上更直觀一點。在 MobX 中,我們借住 ES6 的 class
實現 store,來看看代碼:
// /store/todoStore.ts
import {
makeAutoObservable } from "mobx";
export interface Todo {
id: number;
text: string;
done: boolean;
}
const removeTodo = (todos: Todo[], id: number): Todo[] =>
todos.filter((todo) => todo.id !== id);
const addTodo = (todos: Todo[], text: string): Todo[] => [
...todos,
{
id: Math.max(0, Math.max(...todos.map(({
id }) => id))) + 1,
text,
done: false,
},
];
// Todo 總數據源
class TodoStore {
todos: Todo[] = [];
newTodo: string = "";
constructor() {
makeAutoObservable(this);
}
addTodo() {
this.todos = addTodo(this.todos, this.newTodo);
this.newTodo = "";
}
removeTodo(id: number) {
this.todos = removeTodo(this.todos, id);
}
loadTodo(url: string) {
fetch(url)
.then((res) => res.json())
.then((data) => (this.todos = data));
}
}
const todoStore = new TodoStore();
export default todoStore;
上面代碼就是 MobX 中的 store 的寫法。通過 class
定義我們的 todo 應用狀態,其中我們可以直接在 class
中直接定義狀態以及更新狀態的函數。最後我們 new
出一個 todoStore 實例並 export 出去,這樣保證我們的 react 應用中只會有一個 todo 全局狀態。
可以看到比起 redux 要寫一堆 actions, reducers 等等,顯然 MobX 相對非常的方便,也好理解,而且還可以分很多個 store。
唯一不一樣的地方就是 todoStore 這個 class
中的 constructor
。這邊我們引入 mobx 提供的 makeAutoObservable
函數,makeAutoObservable(this)
的用意就是說當我們的應用啟動,new 出 todoStore 的唯一實例的同時,讓 todoStore 變得可被觀察,也就是說可以追蹤 todoStore 所有 state 的變化,並通知整個應用中所有引用了 todoStore 的組件。
組件中 MobX 生效
MobX 中上面就定義好了整個 store 以及相應的 actions 了,因為可以直接對 state 做更改,所以也沒有了 reducer 的概念。接下來就是要在具體的組件中獲取 store。
這邊直接以添加 todo 的例子來看看怎麼使用:
// /components/TodoAdd.tsx
import *