Kon*_*262 7 typescript reactjs material-ui
我正在尝试使用 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
);
Run Code Online (Sandbox Code Playgroud)
然后我将其与 Material-UI 样式的组件 API 一起使用,如下所示......
const Profile = styled(Button)(({ theme }: { theme: ITheme }) => ({
backgroundColor: theme.sidebar.profile.backgroundColor,
paddingTop: 20,
paddingBottom: 20
}));
Run Code Online (Sandbox Code Playgroud)
这在我的 jsx 中工作得很好<Profile />。
对于道具,我基本上使用了此处示例的精确副本
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
});
Run Code Online (Sandbox Code Playgroud)
使用时这在我的 jsx 中工作得很好<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
}));
Run Code Online (Sandbox Code Playgroud)
我尝试的任何其他操作都会让 TypeScript 感到不安。Material-uistyled函数也太复杂了,我无法理解。
非常感谢,
小智 9
这个问题也几乎让我发疯,但是我已经设法用这种方法使它工作:
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)
Run Code Online (Sandbox Code Playgroud)
我不确定使用样式组件或材质styledHOC 是否有意义,因为它们更适合设置不依赖于 Props 的固定样式。
style但是你可以通过组件的 prop来设置你想要的样式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 );
Run Code Online (Sandbox Code Playgroud)
我们说我们Profile需要两个AddedProps:颜色和主题。我们InnerProfile假设这些道具存在。然后在一个单独的步骤中,我们应用withThemeHOC 以便theme设置 prop。该color道具是必需的,并且必须由您在使用时设置<Profile />。
现在来看看这个古怪的疯狂:
color: (theme as MyTheme).sidebar?.profile?.backgroundColor
Run Code Online (Sandbox Code Playgroud)
发生的情况是,withTheme它知道它注入了一个主题,但它不知道它注入了您的特定主题,因此打字稿根本不知道该主题有一个属性sidebar,因为这是您添加的自定义属性。您需要通过执行以下操作来告诉打字稿“假设该主题具有 MyTheme 的属性” (theme as MyTheme)。MyTheme您可以通过typeof在创建自定义主题的对象上使用来获取该类型。
由于我无权访问您的自定义主题对象,因此我所做的就是定义一个具有所需属性路径的接口,但所有内容都是可选的。看起来像:
interface MyTheme extends Theme {
sidebar?: {
profile?: {
backgroundColor?: string;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我?.在访问时使用了打字稿符号sidebar?.profile?.backgroundColor以避免“对象可能未定义”错误。
| 归档时间: |
|
| 查看次数: |
11394 次 |
| 最近记录: |