У меня есть компонент Application
, который может получить объект темы с реквизитом. Затем тема сохраняется в контексте с помощью ловушки React.createContext
:
import React from 'react'
export interface Theme {
colors: string[]
images: string[]
}
interface ThemeContextParam {
theme: Theme
setTheme: (newTheme: Theme) => void
}
interface Props {
theme: Theme
}
// C O N T E X T
export const ThemeContext = React.createContext<ThemeContextParam>({} as ThemeContextParam)
// C O M P O N E N T
const Application: React.FunctionComponent<Props> = (props) => {
const {
theme: propsTheme,
children
} = props
const [themeState, setThemeState] = React.useState<Theme>(propsTheme)
const themeContextProviderValue = {
theme: themeState,
setTheme: setThemeState
}
return (
<ThemeContext.Provider value={themeContextProviderValue}>
{children}
</ThemeContext.Provider>
)
}
export default Application
Я инициализирую контекст, вызывая компонент Application
:
// C O M P O N E N T
const Theme = (): JSX.Element => {
return (
<Application theme={myTheme}>
<App />
</Application>
)
}
Так что я могу использовать такой контекст:
import { ThemeContext } from '../Application'
// C O M P O N E N T
const App = (): JSX.Element => {
const { theme } = React.useContext(ThemeContext)
...
Но теперь я хочу, чтобы мой Theme
был обобщенным c, чтобы разработчики могли хранить в контексте все, что они хотят, а не просто объект {colors: string[], images: string[]}
. Обобщение c будет передано в компонент Application
следующим образом:
<Application<CustomThemeType> theme={myTheme}>
Поэтому я реализую типы обобщений в Application
:
import React from 'react'
// I N T E R F A C E S
export interface Theme {
colors: string[]
images: string[]
}
interface ThemeContextParam<T extends Theme = Theme> {
theme: T,
setTheme: (newTheme: T) => void
}
interface Props<T extends Theme> {
theme: T
}
// C O N T E X T
export const ThemeContext = React.createContext<ThemeContextParam>({} as ThemeContextParam)
// C O M P O N E N T
const Application = <T extends Theme>(props: Props<T> & { children?: React.ReactNode }): JSX.Element => {
const {
theme: propsTheme
children
} = props
const [themeState, setThemeState] = React.useState<T>(propsTheme)
const themeContextProviderValue = {
theme: themeState,
setTheme: setThemeState
}
return (
<ThemeContext.Provider value={themeContextProviderValue}>
{children}
</ThemeContext.Provider>
)
}
Но, как вы можете см. контекст ThemeContext
не обрабатывает тип generi c. Если я хочу обработать шаблон c, мне нужно создать его экземпляр в самом компоненте следующим образом:
const Application = <T extends Theme>(props: Props<T> & { children?: React.ReactNode }): JSX.Element => {
const ThemeContext = React.createContext<ThemeContextParam<T>>({} as ThemeContextParam<T>)
Но в этом случае я не могу export
мой ThemeContext
.
Итак, кто-то знает, как я могу создать этот контекст, используя обобщенный тип c и экспортировать его?