unstate-next 的实现原理
定义实现 Container 接口#
需要实现包装方法和获取数据的 hooks
/**
* 实现接口
*/
export interface Container<Value, State> {
Provider: React.ComponentType<ContainerProviderProps<State>>;
useContainer: () => Value;
}
定义实现 Provider 接口#
定义接口需要初始化参数和需要使用的子节点。
/**
* ContainerProviderProps 定义类型
* @param {State} State
* @return {State} initialState
* @return {React.ReactNode} children
*/
export interface ContainerProviderProps<State = any> {
initialState?: State;
children: React.ReactNode;
}
createContainer 方法#
在 createContainer 方法中,使用后会返回两个方法 Provider 和 useContainer。
步骤:
- 使用 React.createContext 创建 Context;
- 自定义 hooks 获取属性;
- 需要使用 Context 子组件使用 Provider 包装, 将数据写入 Context;
- 使用 React.useContext 从 Context 中获取属性
export function createContainer<Value, State = void>(
useHook: (initialState?: State) => Value
): Container<Value, State> {
// 使用React.createContext 创建Context
const Context = React.createContext<Value | typeof EMPTY>(EMPTY);
function Provider(props: ContainerProviderProps<State>) {
// 自定义hooks 获取属性
let value = useHook(props.initialState);
// 需要使用Context 子组件使用Provider 包装, 将数据写入Context。
return <Context.Provider value={value}>{props?.children}</Context.Provider>;
}
function useContainer(): Value {
// 使用React.useContext 从 Context 中获取属性
let value = React.useContext(Context);
if (value === EMPTY) {
throw new Error("Component must be wrapped with <Container.Provider>");
}
return value;
}
return {
Provider,
useContainer,
};
}
useContainer#
使用 useContainer 从 Container 中直接获取属性。
export function useContainer<Value, State = void>(
container: Container<Value, State>
): Value {
return container.useContainer();
}
unstate-next 使用#
实现 code#
import React from "react";
const EMPTY: unique symbol = Symbol();
/**
* ContainerProviderProps 定义类型
* @param {State} State
* @return {State} initialState
* @return {React.ReactNode} children
*/
export interface ContainerProviderProps<State = any> {
initialState?: State;
children: React.ReactNode;
}
/**
* 实现接口
*/
export interface Container<Value, State> {
Provider: React.ComponentType<ContainerProviderProps<State>>;
useContainer: () => Value;
}
export function createContainer<Value, State = void>(
useHook: (initialState?: State) => Value
): Container<Value, State> {
// 使用React.createContext 创建Context
const Context = React.createContext<Value | typeof EMPTY>(EMPTY);
function Provider(props: ContainerProviderProps<State>) {
// 自定义hooks 获取属性
let value = useHook(props.initialState);
// 需要使用Context 子组件使用Provider 包装, 将数据写入Context。
return <Context.Provider value={value}>{props?.children}</Context.Provider>;
}
function useContainer(): Value {
// 使用React.useContext 从 Context 中获取属性
let value = React.useContext(Context);
if (value === EMPTY) {
throw new Error("Component must be wrapped with <Container.Provider>");
}
return value;
}
return {
Provider,
useContainer,
};
}
export function useContainer<Value, State = void>(
container: Container<Value, State>
): Value {
return container.useContainer();
}
本文由 note.batype.com 导入。
相关文章
- unstate-next 的使用
Code-Test
- 对象属性只读(递归)DeepReadonly
实现一个泛型 DeepReadonly<T ,它将对象的每个参数及其子对象递归地设为只读。
- 获取只读属性 GetReadonlyKeys
实现泛型 GetReadonlyKeys<T , GetReadonlyKeys<T 返回由对象 T 所有只读属性的键组成的联合类型。