unstate-next 的实现原理

·157 字 · 约 1 分钟#前端#TypeScript#react#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 方法中,使用后会返回两个方法 ProvideruseContainer

步骤:

  1. 使用 React.createContext 创建 Context;
  2. 自定义 hooks 获取属性;
  3. 需要使用 Context 子组件使用 Provider 包装, 将数据写入 Context;
  4. 使用 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 导入。

相关文章