如何创建可传入内外组件作为Props的React包装器组件?
解决React通用Context包装组件的实现问题
错误原因分析
你之前的代码报错是因为混淆了组件类型和React元素实例:
WrappedComponent定义时接收的OutterComponent是React.JSX.ElementType(即组件函数/类),但调用时传入的<Tooltip .../>是已经创建好的React元素(本质是对象),不符合组件类型的要求,因此抛出"Element type is invalid"错误。
正确实现方案
要实现一个能接收任意Context Provider数组、动态包装子元素的通用组件,可按以下步骤编写:
1. 定义TypeScript类型
先明确组件的Props类型,支持传入多个Provider的配置:
// 单个Provider的配置:组件类型 + 可选的组件Props type ProviderConfig = { component: React.JSX.ElementType; props?: React.ComponentProps<any>; }; // Context包装组件的Props type ContextWrapperProps = { providers?: ProviderConfig[]; children: React.ReactNode; };
2. 实现通用包装组件
使用reduceRight从内到外依次用每个Provider包裹子元素:
const ContextWrapper: React.FC<ContextWrapperProps> = ({ providers = [], children }) => { return providers.reduceRight((wrappedContent, { component: Provider, props }) => { return <Provider {...props}>{wrappedContent}</Provider>; }, children); };
3. 使用示例
假设你有两个Context,需要同时包装子组件:
// 示例Context定义 const ThemeContext = React.createContext<'light' | 'dark'>('light'); const AuthContext = React.createContext<{ user: string | null }>({ user: null }); // 使用ContextWrapper const App = () => { return ( <ContextWrapper providers={[ { component: ThemeContext.Provider, props: { value: 'dark' }, }, { component: AuthContext.Provider, props: { value: { user: 'test-user' } }, }, ]} > {/* 这里的所有子元素都能访问ThemeContext和AuthContext */} <Button>Button text</Button> </ContextWrapper> ); };
核心逻辑说明
reduceRight确保数组中第一个Provider是最外层的包裹组件,最后一个是最内层的,符合React组件嵌套逻辑。- 传入的是组件类型(如
ThemeContext.Provider)而非元素实例,组件内部可以动态渲染并传入对应的props。
需求适配
如果需要选择性传入Context,只需调整providers数组的内容即可——不传或传空数组时,子元素直接渲染,不会被任何Provider包装。
内容的提问来源于stack exchange,提问作者lowcrawler
相关产品推荐
相关产品推荐

