👉 unstated-next 基於 React 心智模型(hook+context)而設計的狀態管理。 👈
在 react hook 出現以前,有基於單一數據源,使用純函數修改狀態的 redux & react-redux 也有基於 Object.defineProperty 和 Proxy 來進行數據攔截訪問的 mobx ,但伴隨着 react 16.8 的出現,咱們能夠基於自帶的 hook 去實現狀態管理也就是 unstated-nextjavascript
... 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改形成提供狀態和方法的組件 let Counter = createContainer(useCounter); function CounterDisplay() { //從被處理過的 useCounter 中拿到狀態和方法 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 作了什麼?前端
Provider 注入
和 組件獲取獲取 Store
這兩個方法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 }; };
Provider
和useContainer
的對象value
,子節點不變,返回:<xxx.Provider value={方法,狀態...}>{children}</xxx.Provider>
useContainer
拿到 當前 Context.Provider 中的 value 狀態和方法 並返回在 unstated-next 中每個被處理爲 數據對象 的組件若是想要被共享,須要在最外層逐級包裹java
<Container1.Provider> <Container2.Provider> <Container3.Provider>MyApp</Container3.Provider> </Container2.Provider> </Container1.Provider>
咱們能夠經過 相似 compose 函數進行處理,將全部 數據對象 組件經過 reduce 逐級疊加返回一個相似洋蔥的 Provider,調用的時候只須要使用Provider
包裹住業務組件react
export const composeProvider = (...commonFun) => ({ children }) => { return commonFun.reduceRight((child, { init, Provider }) => { return <Provider init={init}>{child}</Provider>; }, children); }; //進行調用 const Provider = reduceProvider({ ...xxxState1, init: 100 }, xxxState2); export default () => ( <Provider> <ExamplePage1 /> <ExamplePage2 /> <ExamplePage3 /> </Provider> );
查看完整代碼git
大功告成!github
總結redux
其實 unstated-next 實現很簡單,通俗來說就是一個閉包,使用於簡單的業務場景,且寫法過於靈活,一旦遇到 class 組件的狀況,就又要回到舊的寫法,因此只能說有利有弊微信
至此,謝謝各位在百忙之中點開這篇文章,但願對大家能有所幫助,相信你對 unstated-next 有了大概的認實,若有問題歡迎各位大佬指正。閉包
歡迎添加個人微信共同討論前端技術問題(備註:qian)ide
求個 star,謝謝你們了