1、介绍
轻量级的React状态管理工具
2、安装
安装 npm install --save unstated-next
3、API 使用及优化
createContainer(useHook) <Container.Provider> <Container.Provider initialState> Container.useContainer() useContainer(Container)
Example:
import React, { useState, createContext, useContext, useCallback } from "react"; import { createContainer } from "unstated-next"; // import { createContainer } from "./unstated-next"; // 通过自定义hook 共享逻辑 function useConter(initialState = 0) { let [count, setCount] = useState(initialState); let decrement = useCallback(() => setCount(count - 1), [count]); let increment = useCallback(() => setCount(count + 1), [count]); return { count, decrement, increment, }; } // 通过Context共享状态 let Counter = createContainer(useConter); console.log(Counter, "Counter....111"); // let Counter = createContext(null); function InnerCounter() { let counter = Counter.useContainer(); return ( <div> <button onClick={counter.decrement}>-</button> <p>You clicked {counter.count} times</p> <button onClick={counter.increment}>+</button> </div> ); } function CounterHandle() { let counter = Counter.useContainer(Counter); return ( <div> <CounterDisplay {...counter}></CounterDisplay> </div> ); } let CounterDisplay = React.memo((props) => { return ( <div> <button onClick={props.decrement}>-</button> <p>You clicked {props.count} times</p> <button onClick={props.increment}>+</button> </div> ); }); function App() { return ( <Counter.Provider initialState={2}> <CounterHandle /> <Counter.Provider initialState={1}> <InnerCounter /> </Counter.Provider> </Counter.Provider> ); } export default App;
4、原理
- 通过React.createContext() API 提供Provider, 通过React.useContext获取最新状态, 在Provider方法上调用用户自定义的useHook, 拿到最新的状态和方法注入, 通过useContainer获取最新的值
- 解决: 如何拿到Provider 上设置的 initialState, 通过重写Context对象上的Provider方法通过props传入拿到
简版源码
import React, { createContext, useContext } from "react"; export function createContainer(useHook) { let Context = createContext(null); const Provider = function Provider(props) { let value = useHook(props.initialState); return <Context.Provider value={value}>{props.children}</Context.Provider>; }; const useContainer = function () { let value = useContext(Context); return value; }; return { Provider, useContainer, }; }