20 行簡單實現(xiàn)一個 unstated-next ??

前言 ??

?? unstated-next 基于 React 心智模型(hook+context)而設(shè)計的狀態(tài)管理。 ??

Alt

在 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 做了什么畏纲?

  1. 提供 createContainer 將自定義 Hooks 封裝為一個可以提供狀態(tài)和方法的 數(shù)據(jù)對象
  2. 利用 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ù)返回一個包含ProvideruseContainer的對象
  • 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>)

參考文獻

求個 star贮尖,謝謝大家了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市趁怔,隨后出現(xiàn)的幾起案子湿硝,更是在濱河造成了極大的恐慌,老刑警劉巖痕钢,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件图柏,死亡現(xiàn)場離奇詭異,居然都是意外死亡任连,警方通過查閱死者的電腦和手機蚤吹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人裁着,你說我怎么就攤上這事繁涂。” “怎么了二驰?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵扔罪,是天一觀的道長。 經(jīng)常有香客問我桶雀,道長矿酵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任矗积,我火速辦了婚禮全肮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棘捣。我一直安慰自己辜腺,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布乍恐。 她就那樣靜靜地躺著评疗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茵烈。 梳的紋絲不亂的頭發(fā)上百匆,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音瞧毙,去河邊找鬼胧华。 笑死,一個胖子當著我的面吹牛宙彪,可吹牛的內(nèi)容都是我干的矩动。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼释漆,長吁一口氣:“原來是場噩夢啊……” “哼悲没!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起男图,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤示姿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逊笆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栈戳,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年难裆,在試婚紗的時候發(fā)現(xiàn)自己被綠了子檀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镊掖。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖褂痰,靈堂內(nèi)的尸體忽然破棺而出亩进,到底是詐尸還是另有隱情,我是刑警寧澤缩歪,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布归薛,位于F島的核電站,受9級特大地震影響匪蝙,放射性物質(zhì)發(fā)生泄漏主籍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一骗污、第九天 我趴在偏房一處隱蔽的房頂上張望崇猫。 院中可真熱鬧沈条,春花似錦需忿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至月而,卻和暖如春汗洒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背父款。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工溢谤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憨攒。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓世杀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肝集。 傳聞我的和親對象是個殘疾皇子瞻坝,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容