react可组合Hook链

14 阅读2分钟

基于需求描述,我们设计一套符合「可组合Hook链」的React组件工厂方案,以下是核心实现:

type Hook<TViewProps, TAsset extends Record<string, unknown>> = (
  props: TAsset & { initialProps: Readonly<TViewProps> },
  next: (modifiedAsset?: Partial<TAsset>) => void
) => Partial<TAsset> | void;

type CardFactoryOptions<TViewProps, TAsset extends Record<string, unknown>> = {
  view: React.ComponentType<TViewProps>,
  hooks?: Hook<TViewProps, TAsset>[],
  initialAsset?: TAsset
};

function createCardComponent<TViewProps, TAsset extends Record<string, unknown>>(
  options: CardFactoryOptions<TViewProps, TAsset>
) {
  return (props: TViewProps) => {
    const { view: View, hooks = [], initialAsset = {} as TAsset } = options;
    
    // Hook链执行核心逻辑
    const executeHooksChain = (): TViewProps => {
      let currentAsset: TAsset = { ...initialAsset };
      let viewProps: Partial<TViewProps> = {};

      const invokeNextHook = (index: number, modifiedAsset?: Partial<TAsset>) => {
        if (modifiedAsset) {
          currentAsset = Object.assign({}, currentAsset, modifiedAsset);
        }

        if (index >= hooks.length) {
          // 最后一个Hook处理最终参数
          viewProps = Object.assign({}, props, currentAsset);
          return;
        }

        const hook = hooks[index];
        const hookResult = hook(
          { ...currentAsset, initialProps: props },
          (nextModifiedAsset) => invokeNextHook(index + 1, nextModifiedAsset)
        );

        // 允许同步返回修改结果
        if (hookResult) {
          currentAsset = Object.assign({}, currentAsset, hookResult);
        }
      };

      invokeNextHook(0);
      return viewProps as TViewProps;
    };

    return <View {...executeHooksChain()} />;
  };
}

1、hook链执行机制:

// Hook类型定义(支持异步扩展)
type Hook<TViewProps, TAsset> = (
  props: { initialProps: TViewProps } & TAsset,
  next: (asset?: Partial<TAsset>) => void
) => Partial<TAsset> | void;

2、资产asset管理模式:

let currentAsset: TAsset = { ...initialAsset };

// Hook内修改资产示例
const dataMappingHook: Hook<ViewProps, Asset> = ({ initialProps }, next) => {
  const mappedData = transform(initialProps.rawData);
  next({ mappedData }); // 将处理结果传递给下游
};

3、终止与回流控制

// 禁止回流的实现方式
const invokeNextHook = (index: number) => {
  if (index >= hooks.length) return;
  
  const hook = hooks[index];
  hook(combinedProps, (modifiedAsset) => {
    // 新资产只能向前传递,无法影响已执行Hook
    invokeNextHook(index + 1, modifiedAsset);
  });
};

应用场景

1、基础数据流处理


// 定义业务Hooks
const useDataMapping: Hook<ViewProps, { mappedData: DataType }> = 
  ({ initialProps }) => ({ mappedData: mapData(initialProps.rawData) });

const useSideEffects: Hook<ViewProps, { mappedData: DataType }> = 
  ({ mappedData }, next) => {
    useEffect(() => fetchDetail(mappedData.id), [mappedData]);
    return { logData: generateLog(mappedData) };
  };

// 组合组件
const SmartCard = createCardComponent({
  view: BaseCardView,
  hooks: [useDataMapping, useSideEffects],
});

2、动态条件拦截


const usePermissionCheck: Hook<ViewProps, {}> = 
  ({ initialProps }, next) => {
    if (!checkPermission(initialProps.userRole)) {
      next({ disabled: true }); // 阻断后续Hook执行
    }
  };

const useFinalHandler: Hook<ViewProps, { disabled?: boolean }> = 
  ({ disabled }, next) => {
    return { 
      buttonText: disabled ? '无权操作' : '确认提交',
      onClick: disabled ? undefined : handleSubmit
    };
  };

// 创建带权限检查的卡片
const SecureCard = createCardComponent({
  view: ActionCard,
  hooks: [usePermissionCheck, useFinalHandler],
});

核心实现,是把入参或者输入数据,当成资产asset处理,形成【资产管道】的概念,基于纯数据处理的方案,实现hook之间的低耦合写作,既满足复杂业务场景的定制需求,又能通过标准化协议保障系统稳定性,后续可动态拓展中间件机制,增强异常处理、性能监控、埋点等能力。