You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建可自动推导子组件类型的泛型React Context?

React泛型Context实现子组件自动类型推导方案

完全可行,核心是让TabsRoot的泛型类型自动传递给子组件,无需手动为TabsHeader指定泛型。你之前的实现问题在于TabsRoot的children被定义为React.ReactNode,无法携带泛型信息,导致子组件无法自动推导类型。下面是修改后的完整实现:

完整代码实现

import React, { Dispatch, SetStateAction, useState, useContext } from 'react';

type Headers = 'Foo' | 'Bar' | 'Baz';
const defaultValue: Headers = 'Foo';

type TabsContextProps<T> = {
  activeTab: T;
  setActiveTab: Dispatch<SetStateAction<T>>;
};

const TabsContext = React.createContext<TabsContextProps<any> | undefined>(undefined);

// 改造TabsRootProps,让children成为接收上下文的函数(Render Props模式)
type TabsRootProps<T> = {
  defaultValue: T;
  children: (context: TabsContextProps<T>) => React.ReactNode;
};

export function TabsRoot<T>({ defaultValue, children }: TabsRootProps<T>) {
  const [activeTab, setActiveTab] = useState<T>(defaultValue);

  const contextValue: TabsContextProps<T> = {
    activeTab,
    setActiveTab,
  };

  return (
    <TabsContext.Provider value={contextValue}>
      {children(contextValue)}
    </TabsContext.Provider>
  );
}

function useTabsRootContext<T>(): TabsContextProps<T> {
  const context = useContext(TabsContext);
  if (!context) {
    throw new Error('useTabsRootContext must be used inside TabsRoot');
  }
  return context as TabsContextProps<T>;
}

// TabsHeader无需手动指定泛型,自动从Context推导类型
const TabsHeader = <T>({ value }: { value: T }) => {
  const { activeTab } = useTabsRootContext<T>();
  if (activeTab !== value) {
    return null;
  }
  return <p>Im Active</p>;
};

// 理想用法:子组件自动推导类型,错误值触发TypeScript报错
const Tabs = () => {
  return (
    <TabsRoot defaultValue={defaultValue}>
      {() => (
        <>
          <TabsHeader value="Baz" />
          <TabsHeader value="error" /> {/* TypeScript直接报错:类型"error"不能赋值给类型Headers */}
        </>
      )}
    </TabsRoot>
  );
};

关键改动说明

  1. Render Props传递泛型:将TabsRoot的children改为函数,TabsRoot的泛型T会通过defaultValue自动推导,子函数内部的所有组件都能共享该类型。
  2. 修复状态初始化:原代码中useState未使用defaultValue,导致初始activeTab为undefined,现在修正为用defaultValue初始化。
  3. 简化TabsHeader类型:去掉手动指定泛型的逻辑,直接从useTabsRootContext推导类型,确保value与上下文的activeTab类型完全匹配。

这种方案既实现了类型自动推导,又保证了类型安全性,完全符合你期望的用法。

内容的提问来源于stack exchange,提问作者Martin Hansson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 04:57:05