我正在尝试使用Material UI样式的组件API来注入自定义主题和一些道具到特定的自定义元素。
我有一个自定义主题或一些道具,但不能同时使用
我的自定义主题在单独的文件中定义如下...
export interface ITheme extends Theme {
sidebar: SideBarTheme;
}
type SideBarTheme = {
// Various properties
};
const theme = createMuiTheme(
{
// Normal theme modifications
},
{
sidebar: {
// Custom theme modifications
},
} as ITheme
);
然后我将其与Material-UI样式的组件API结合使用,如下所示。...
const Profile = styled(Button)(({ theme }: { theme: ITheme }) => ({
backgroundColor: theme.sidebar.profile.backgroundColor,
paddingTop: 20,
paddingBottom: 20
}));
在我的jsx中使用<Profile />
可以正常工作。
对于道具,我本质上是使用示例here
的精确副本interface MyButtonProps {
color: string;
}
const Profile = styled( ({ color, ...other }: MyButtonProps & Omit<ButtonProps, keyof MyButtonProps>) => (
<Button {...other} />
))({
backgroundColor: (props: MyButtonProps) => props.color,
paddingTop: 20,
paddingBottom: 20
});
使用<Profile color="red"/>
如何使这两种字体与打字稿一起使用?
我从字面上试图像下面这样组合它们,但道具不会消失...
const Profile = styled( ({ color, ...other }: MyButtonProps & Omit<ButtonProps, keyof MyButtonProps>) => (
<Button {...other} />
))(({ theme }: { theme: ITheme }) => ({
backgroundColor: (props: MyButtonProps) => props.color,
color: theme.sidebar.profile.backgroundColor,
paddingTop: 20,
paddingBottom: 20
}));
我尝试做的其他任何事情都只会破坏TypeScript。 Material-ui styled
函数也太复杂了,我无法理解。
非常感谢,
答案 0 :(得分:2)
这个问题也几乎把我逼疯了,但我已经设法用这种方法让它工作了:
import React from 'react'
import { styled, Theme, withTheme } from '@material-ui/core/styles'
import { Box, BoxProps } from '@material-ui/core'
interface SidebarSectionProps {
padded?: boolean
theme: Theme
}
export const SidebarSectionComponent = styled(
(props: SidebarSectionProps & BoxProps) => <Box {...props} />
)({
marginBottom: ({ theme }: SidebarSectionProps) => theme.spacing(3),
paddingLeft: ({ theme, padded }: SidebarSectionProps) =>
padded ? theme.spacing(3) : 0,
paddingRight: ({ theme, padded }: SidebarSectionProps) =>
padded ? theme.spacing(3) : 0
})
export const SidebarSection = withTheme(SidebarSectionComponent)
答案 1 :(得分:1)
我不确定使用样式组件或材质styled
HOC是否有意义,因为它们对于设置不依赖于道具的固定样式更好。
但是您可以通过style
组件的Button
道具来设置所需的样式。
这似乎是可行的解决方案:
interface AddedProps {
theme: Theme;
color: string;
};
type InnerProps = AddedProps & Omit<ButtonProps, keyof AddedProps>
const InnerProfile = ({color, theme, ...other}: InnerProps) => (
<Button
{...other}
style={{
...other.style,
paddingTop: 20,
paddingBottom: 20,
backgroundColor: color,
color: (theme as MyTheme).sidebar?.profile?.backgroundColor,
}}
/>
)
export const Profile = withTheme( InnerProfile );
我们说Profile
需要两个AddedProps
:颜色和主题。我们写InnerProfile
假设那些道具存在。然后,在一个单独的步骤中,我们应用withTheme
HOC,以便设置theme
属性。 color
属性是必需的,使用<Profile />
时必须由您设置。
现在是因为这种疯狂的疯狂行为:
color: (theme as MyTheme).sidebar?.profile?.backgroundColor
发生了什么事,withTheme
知道它注入了一个主题,但它不知道它注入了您的特定主题,所以打字稿不知道该主题完全具有属性sidebar
,因为这是您添加的自定义属性。您需要通过执行(theme as MyTheme)
来告诉打字稿“假设该主题具有MyTheme的属性”。您可以通过在创建自定义主题的对象上使用MyTheme
来获得该类型typeof
。
由于我无权访问您的自定义主题对象,因此我要做的是定义一个接口,该接口具有所需的属性路径,但所有选项都是可选的。看起来像:
interface MyTheme extends Theme {
sidebar?: {
profile?: {
backgroundColor?: string;
}
}
}
在访问?.
时,我使用了打字稿sidebar?.profile?.backgroundColor
表示法,以避免“对象可能未定义”错误。