前言 📝
👉 unstated-next 基于 React 心智模型(hook+context)而设计的状态治理。 👈
在 react hook 呈现之前,有基于繁多数据源,应用纯函数批改状态的 redux & react-redux 也有基于 Object.defineProperty 和 Proxy 来进行数据拦挡拜访的 mobx ,但随同着 react 16.8 的呈现,咱们能够基于自带的 hook 去实现状态治理也就是 unstated-next
官网 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革新成提供状态和办法的组件
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 做了什么?
- 提供 createContainer 将自定义 Hooks 封装为一个能够提供状态和办法的 数据对象
- 利用 useContext 结构了
Provider 注入
和组件获取获取 Store
这两个办法
实现一个 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 };
};
- 通过函数返回一个蕴含
Provider
和useContainer
的对象 - Provider 承受 init 初始值,去执行 数据对象 组件,通过 createElement 发明一个 Context.Provider 传值组件,并将 数据对象 组件返回的办法和状态保留到
value
,子节点不变,返回:
<xxx.Provider value={办法,状态...}>{children}</xxx.Provider>
- 通过
useContainer
拿到 以后 Context.Provider 中的 value 状态和办法 并返回
如何解决 Provider hell 🏁
在 unstated-next 中每一个被解决为 数据对象 的组件如果想要被共享,须要在最外层逐级包裹
<Container1.Provider>
<Container2.Provider>
<Container3.Provider>MyApp</Container3.Provider>
</Container2.Provider>
</Container1.Provider>
咱们能够通过 相似 compose 函数进行解决,将所有 数据对象 组件通过 reduce 逐级叠加返回一个相似洋葱的 Provider,调用的时候只须要应用Provider
包裹住业务组件
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>
);
查看残缺代码
功败垂成!
总结 💢
总结
其实 unstated-next 实现很简略,艰深来讲就是一个闭包,应用于简略的业务场景,且写法过于灵便,一旦遇到 class 组件的状况,就又要回到旧的写法,所以只能说有利有弊
至此,谢谢各位在百忙之中点开这篇文章,心愿对你们能有所帮忙,置信你对 unstated-next 有了大略的认实,如有问题欢送各位大佬斧正。
欢送增加我的微信独特探讨前端技术问题(备注:qian)
- 👋:跳转 github
参考文献
- 🍑:unstated-next
- 🍑:React hooks,组合与形象,状态治理
- 🍑:精读《unstated 与 unstated-next 源码》
- 🍑:React 轻量状态治理库 unstated-next 应用教程
求个 star,谢谢大家了
发表回复