我在思考如何创建通用上下文时遇到了一些麻烦。 基本上我想要的是能够将一个值传递给根,然后让孩子们推断正确的类型,这可能吗?我知道这很有可能,因为
TabHeaderProps
、TabContextProps
和 TabRootProps
之间没有任何联系。
这是一个有效的简化版本,但它比我想要的更详细。
import React, { Dispatch, SetStateAction, useState } from 'react';
type Headers = 'Foo' | 'Bar' | 'Baz';
const defaultValue: Headers = 'Foo';
type TabsContextProps<T = any> = {
activeTab: T;
setActiveTab: Dispatch<SetStateAction<T | undefined>>;
};
const TabsContext = React.createContext<TabsContextProps | undefined>(
undefined,
);
type TabsRootProps<T> = {
defaultValue: T;
children: React.ReactNode;
};
export function TabsRoot<T>({ children }: TabsRootProps<T>) {
const [activeTab, setActiveTab] = useState<T>();
return (
<TabsContext.Provider
value={{
setActiveTab,
activeTab,
}}
>
{children}
</TabsContext.Provider>
);
}
function useTabsRootContext<T>(): TabsContextProps<T> {
if (!React.useContext(TabsContext)) {
throw new Error('useTabsRootContext must be used inside TabsRoot');
}
return React.useContext(TabsContext) as TabsContextProps<T>;
}
type TabHeaderProps<T> = {
value: T;
};
const TabsHeader = <T,>({ value }: TabHeaderProps<T>) => {
const { activeTab } = useTabsRootContext<T>();
if (!activeTab !== value) {
return null;
}
return <p>Im Active</p>;
};
const Tabs = () => {
<TabsRoot<Headers> defaultValue={defaultValue}>
<TabsHeader<Headers> value="Baz" /> {/* This work but i preferably want this to be infered based on the TabsRootType */}
</TabsRoot>;
};
理想情况下我想要它:
const Tabs = () => {
<TabsRoot defaultValue={defaultValue}>
<TabsHeader value="Baz" />
<TabsHeader value="error" /> {/* I want this to throw an error */}
</TabsRoot>;
};
不幸的是,这确实是不可能的: