一提起 React 狀態管理,不少人就提也不想提。html
Redux: 1 號選手,人氣最高的一個,得與 react-redux
一同使用。本身無論異步,因此常聽到的什麼 redux-thunk
、redux-saga
是其下屬,專門擦屁股的。特色就是難用,若是按照官方文檔的寫法用,基本就是想死。推薦閱讀:www.zhihu.com/question/33…vue
Mobx: 2 號選手,使用監聽的方式,與 React 的思想背道而馳,思想有問題,流氓!react
dva: Redux 封裝,使用了 redux-saga
,generator 的寫法,想死。git
Rematch: Redux 封裝,相似 dva,model
中分爲 reducers
和 effects
,不夠簡潔。github
廣告:因此仍是 🐤 Retalk 最簡單,史上最簡單的 Redux 封裝,走過路過不要錯過:github.com/nanxiaobei/…vuex
無論怎麼說,Hooks 來了,之前的狀態管理都是給之前的開發方式用的,爲了對 Hooks 有點表示,也就加幾個 useBlabla()
完事。redux
與 Hooks 的輕靈相比,它們都顯得笨重、老態龍鍾、敷衍。bash
有沒有專用於 Hooks 的狀態管理呢?目前尚未衆望所歸的,基本都是老選手搞個兼職,有點不三不四。服務器
不夠革命。異步
一個是爲了解決相鄰組件的通訊問題。
雖然能夠經過「狀態提高」解決,但有兩個問題:
每次子組件更新,都會觸發負責下發狀態的父組件的總體更新(使用 Context 也有這個問題),而後寫一大堆 PureComponent
、shouldComponentUpdate
,代碼還能看嗎?React 設計中的糟粕寫了個夠,太慘。
邏輯比較多的話,都寫在父組件裏,代碼還能看嗎?根本不考慮父組件的感覺。
因此「狀態提高」不是個好思路,仍是須要狀態管理。
另外,狀態管理最重要的一個好處,就是 ——
它能夠把「與服務器交互」和「操做數據」的邏輯,從組件中提取出去,組件只用接收處理好的數據便可。這就至關於分離了個 Service 層出去,很好的開發模式。
代碼邏輯分離,各司其職,組件去幹組件該乾的事,這纔是最大的好處。
因此咱們須要狀態管理。
若是一開始是從 Redux 上手,會發現它提供了一個全局的 store。而後呢?而後它也沒說什麼話,有什麼問題就本身解決吧,我先睡了。
實際業務開發中,遇到的最多見的場景,就是須要區分不一樣的「模塊」,這是最基本的需求。
Vuex 比較務實,提供了 modules
的概念。
Redux 呢?固然是得靠你本身啦,咱們提供一個理念就好了,這麼簡單的東西,你就本身去搞吧。
若是不從 API 設計上進行規範,必然會致使無數不一樣的實現。(單押 x 2)
CHAOS.
咱們須要什麼樣的狀態管理?
咱們須要符合中國特點社會主義初級階段國情的狀態管理。
咱們須要能夠劃分不一樣的模塊,模塊是獨立的,同時模塊間又是能夠自由溝通的。
不少狀態管理庫只考慮了模塊的「獨立」,可是對「溝通」保持沉默,這是不友好的。
獨立,且連通 —— 這纔是模塊的意義所在。
通常來講,推薦按照基本的路由入口,劃分出不一樣的模塊,這也是 dva 中的思路(它的文件夾乾脆就叫 routes
)。
這也符合天然的思惟方式,劃分路由,也就是自然的認爲它們屬於不一樣的模塊。
而每一個狀態管理的模塊,咱們稱之爲 "model",建議與路由入口組件綁定起來,每一個入口組件及其子組件,總體對應一個 model。
---A
index.jsx
model.js
---B
index.jsx
model.js
---C
index.jsx
model.js
複製代碼
模塊是獨立的,毋庸置疑,模塊模塊,不獨立還叫模塊嗎?
那模塊如何溝通呢?
在組件中,能夠獲取到自身 model 和其它的 model,這並不難。
主要是,在 model 內部,自身各個方法須要互相調用,同時須要拿到其它 model 的數據和方法,這纔是溝通的意義。
還得足夠簡單。
這樣纔是一個良好而完全的設計。
最直接的,咱們但願在組件中,經過 Hooks 去訪問到某個 model。
const { someStateInA, someActionInA } = useModel(a);
// or
const { someStateInA, someActionInA, someStateInB, someActionInB } = useModels(a, b);
複製代碼
useModel()
中傳入某個 model,這樣設計的話,須要哪一個 model,就得在組件中引入 model 的文件,不夠自由,不能依賴於必須去引入文件。
只要操做麻煩,代碼寫的變多,就不是好的設計。
另外 Hooks 是爲了讓代碼更清晰,咱們不能像 Mobx 同樣,違背總體系統的設計哲學。
因此 model 獲取最好是分開的,useModels(a, b)
一次性引入多個 model 的方式,不夠清晰。
不能依賴文件,引入得清晰,因此:
const { someStateInA, someActionInA } = useModel('a');
const { someStateInB, someActionInB } = useModel('b');
複製代碼
依賴一個字符串,這樣就不須要在每一個組件中引入文件。useModel()
只能訪問一個 model,代碼足夠清晰。
這是咱們須要的設計。
一個 model 整體來講能夠分爲兩大塊,數據(state
)和操做數據的方法(reducers
、effects
)。
reducers
與 effects
,或者 Vuex 中的 mutations
與 actions
,是爲了區分直接改變和異步操做,同步函數和異步函數。不夠簡潔,能不能合併成一個?
答案能夠的,咱們稱之爲 actions
。
更新 state 的方法,直接注入 model 中,因此一個 action 能夠是同步也能夠是異步,它只是被當作函數來調用。
因而,model 中分爲兩塊就好:
exports default {
state: {},
actions: {},
}
複製代碼
model 溝通,主要是實如今 action 中去訪問其它須要的東西。
自由而無限制的溝通。
一個 action 中須要訪問到如下:1. 自身 state,2. 自身 action,3. 其它模塊 state,4. 其它模塊 action,5. 自身 state updater。
簡化一下,就是須要訪問:1. 自身 model,2. 其它 model,3. 自身 state updater。
再簡化一下:1. model,2. 自身 state updater。
因此其實只須要兩個方法:getModel()
和 setState()
。
getModel()
獲取自身,getModel('other')
獲取其它。
如何拿到這兩個方法呢?
經過 this
訪問。但咱們是給 Hooks 設計狀態管理,Hooks 就是爲了拋棄 this
,仍是那句話 —— 不能違背系統的設計哲學。
Vuex 中,是在函數第一個參數注入 context,調用時比較反直覺,放棄這種方式。
model 文件中 import 方法進來,太麻煩了,只要操做麻煩,代碼寫的變多,就不是好的設計。
因此惟一的方式(Rematch 的設計中也能看到),就是在參數中注入方法。
也就是把 actions
變爲一個函數:
exports default {
state: {},
actions: ({ getModel, setState }) => ({
someAction() {
const { someState, someOtherAction } = getModel();
}
}),
}
複製代碼
這裏考慮到一個美學問題,getModel()
由於不少 action 都會用到,而實際寫出來時,由於 l
高度的問題,又比較醜,因此就把 API 簡化爲了 model()
。
model()
獲取自身,model('other')
獲取其它。
因而,flooks,福祿克斯,誕生了:
🍸 flooks → github.com/nanxiaobei/…
import { setModel, useModel } from 'flooks';
const a = {
state: {},
actions: ({ model, setState }) => ({
someAction() {
const { someState, someOtherAction } = model();
...
setState(payload);
}
}),
}
setModel('a', a);
function A() {
cosnt { someState, someAction } = useModel('a');
return (
...
)
}
複製代碼
自然的模塊化支持。
只有兩個 API,setModel()
和 useModel()
。
加上 actions
的兩個參數,model()
和 setState()
,就這麼多。
足夠簡單,足夠實現一切。
去中心化,去中心化,去中心化。
一切都爲了更簡單的開發。
再不須要頂層分發 store,不須要 store 文件夾或 store.js 文件。
無需頂層 createStore()
,無需頂層 Provider
。
註冊 model 時,無需先在中心化文件中引入 model,自身文件夾內就能夠搞定一切。
直接用 setModel()
把組件和 model 鏈接起來,就這麼簡單。
模塊化,積木同樣組合,簡潔,靈活,這是咱們的理念。
每一個組件和 model 構成一個自組織,同時它們又能夠訪問到世界各地。它們不用去有關部門報道,就能在世界的任何角落相遇。
這是咱們的哲學:獨立,自由,個體,世界。