react-create-store
Version:
State management just using basic React hooks api within 80 lines of code 在80行代码内仅使用基本的 React hooks API 进行状态管理
79 lines (78 loc) • 3.21 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useMemo, } from "react";
import { useImmerReducer } from "use-immer";
export { useImmer, useImmerReducer } from "use-immer";
/**
* Batch declaring providers in JSX
*
* [idx] where to start, default is 0
*
* [providers] the order of the providers parameter array is exactly the order of the context hierarchy
*
* 在 JSX 中批量声明上下文
*
* [providers] 参数数组的顺序,正好是上下文层级的顺序
*
* [idx] 从哪个位置开始迭代声明,默认是 0
*
* @export
* @param {PropsWithChildren<{
* idx?: number
* providers: FC<PropsWithChildren>[]
* }>} {
* children,
* idx = 0,
* providers,
* }
* @return {*}
*/
export function BatchProviders({ children, idx = 0, providers, }) {
const Provider = providers[idx];
return Provider ? (_jsx(Provider, { children: _jsx(BatchProviders, { idx: idx + 1, providers: providers, children: children }) })) : (children);
}
/**
* Create a store,reducer with immer inside
*
* 创建一个 store, 内部有 immer 的 reducer
*
* @export
* @template S
* @template A
* @template Async
* @param {S} intialState
* [initialState] The initial state of the reducer in the store (cannot be null or undefined)
* [initialState] reducer 的初始状态(不能为 null 或 undefined)
* @param {(state: Draft<S>, action: Partial<A>) => void} reducer
* [reducer] The reducer function of the store,State is immutable(by immer)
* [reducer] store 的 reducer 函数,State 是不可变的(通过 immer)
* @param {(state: S, dispatch: Dispatch<Partial<A>>) => Async} [useHook=() =>
* ({} as unknown as Async)]
* [useHook] A custom hook that returns an object where each property is an asynchronous function({} by default)
* [useHook] 一个自定义 hook,返回一个对象,对象的每个属性都是一个异步函数(默认是 {})
* @return {*}
*/
export default function createStore(intialState, reducer, useHook = () => ({})) {
const StateContext = createContext(intialState);
const DispatchContext = createContext(() => { });
const AsyncContext = createContext({});
return {
useReducer() {
const state = useContext(StateContext);
const dispatch = useContext(DispatchContext);
const async = useContext(AsyncContext);
// 因为 dispatch 和 async 都是稳定不变的,因此返回 state 时,可以顺带一起返回
return [state, dispatch, async];
},
useDispatch() {
return useContext(DispatchContext);
},
useAsync() {
return useContext(AsyncContext);
},
Provider(props) {
const [state, dispatch] = useImmerReducer(reducer, undefined, () => props.initialState === undefined ? intialState : props.initialState);
const async = useHook(state, dispatch);
return (_jsx(StateContext.Provider, { value: state, children: _jsx(DispatchContext.Provider, { value: dispatch, children: _jsx(AsyncContext.Provider, { value: useMemo(() => async, []), children: props.children }) }) }));
},
};
}