前言 ??
?? unstated-next 基于 React 心智模型(hook+context)而設(shè)計的狀態(tài)管理。 ??
在 react hook 出現(xiàn)之前,有基于單一數(shù)據(jù)源,使用純函數(shù)修改狀態(tài)的 redux & react-redux 也有基于 Object.defineProperty 和 Proxy 來進行數(shù)據(jù)攔截訪問的 mobx 炭剪,但伴隨著 react 16.8 的出現(xiàn)乐设,我們可以基于自帶的 hook 去實現(xiàn)狀態(tài)管理也就是 unstated-next
官網(wǎng) Demo ??
...
import { createContainer } from "unstated-next";
function useCounter(initialState = 0) {
let [count, setCount] = useState(initialState);
let decrement = () => setCount(count - 1);
let increment = () => setCount(count + 1);
return { count, decrement, increment };
}
//使用 createContainer 將 useCounter改造成提供狀態(tài)和方法的組件
let Counter = createContainer(useCounter);
function CounterDisplay() {
//從被處理過的 useCounter 中拿到狀態(tài)和方法
let counter = Counter.useContainer();
return (
<div>
<button onClick={counter.decrement}>-</button>
<span>{counter.count}</span>
<button onClick={counter.increment}>+</button>
</div>
);
}
function App() {
return (
<Counter.Provider>
<CounterDisplay />
{/* 通過initialState屬性注入初始值 */}
<Counter.Provider initialState={2}>
<CounterDisplay />
</Counter.Provider>
</Counter.Provider>
);
}
render(<App />, document.getElementById("root"));
unstated-next 做了什么畏纲?
- 提供 createContainer 將自定義 Hooks 封裝為一個可以提供狀態(tài)和方法的 數(shù)據(jù)對象
- 利用 useContext 構(gòu)造了
Provider 注入
和組件獲取獲取 Store
這兩個方法
實現(xiàn)一個 unstated-next ??
import { createContext, createElement, useContext } from "react";
export default useHook => {
const Context = createContext();
const Provider = ({ init, children }) => {
return createElement(Context.Provider, { value: useHook(init) }, children);
};
const useContainer = () => useContext(Context);
return { Provider, useContainer };
};
- 通過函數(shù)返回一個包含
Provider
和useContainer
的對象 - Provider 接受 init 初始值,去執(zhí)行 數(shù)據(jù)對象 組件,通過 createElement 創(chuàng)造一個 Context.Provider 傳值組件桨吊,并將 數(shù)據(jù)對象 組件返回的方法和狀態(tài)保存到
value
,子節(jié)點不變凤巨,返回:
<xxx.Provider value={方法视乐,狀態(tài)...}>{children}</xxx.Provider>
- 通過
useContainer
拿到 當前 Context.Provider 中的 value 狀態(tài)和方法 并返回
如何解決 Provider hell ??
在 unstated-next 中每一個被處理為 數(shù)據(jù)對象 的組件如果想要被共享,需要在最外層逐級包裹
<Container1.Provider>
<Container2.Provider>
<Container3.Provider>MyApp</Container3.Provider>
</Container2.Provider>
</Container1.Provider>
我們可以通過 類似 compose 函數(shù)進行處理敢茁,將所有 數(shù)據(jù)對象 組件通過 reduce 逐級疊加返回一個類似洋蔥的 Provider佑淀,調(diào)用的時候只需要使用Provider
包裹住業(yè)務組件
export const composeProvider = (...commonFun) => ({ children }) => {
return commonFun.reduceRight((child, { init, Provider }) => {
return <Provider init={init}>{child}</Provider>;
}, children);
};
//進行調(diào)用
const Provider = reduceProvider({ ...xxxState1, init: 100 }, xxxState2);
export default () => (
<Provider>
<ExamplePage1 />
<ExamplePage2 />
<ExamplePage3 />
</Provider>
);
大功告成!
總結(jié) ??
總結(jié)
其實 unstated-next 實現(xiàn)很簡單彰檬,通俗來講就是一個閉包伸刃,使用于簡單的業(yè)務場景,且寫法過于靈活逢倍,一旦遇到 class 組件的情況捧颅,就又要回到舊的寫法,所以只能說有利有弊
至此较雕,謝謝各位在百忙之中點開這篇文章碉哑,希望對你們能有所幫助,相信你對 unstated-next 有了大概的認實亮蒋,如有問題歡迎各位大佬指正扣典。
歡迎添加我的微信共同討論前端技術(shù)問題(備注:qian)
[圖片上傳失敗...(image-5e9c59-1618883960364)].png>)
參考文獻
- ??:unstated-next
- ??:React hooks,組合與抽象慎玖,狀態(tài)管理
- ??:精讀《unstated 與 unstated-next 源碼》
- ??:React 輕量狀態(tài)管理庫 unstated-next 使用教程
求個 star贮尖,謝謝大家了