styled-components:使用额外的样式扩展现有组件
Posted
技术标签:
【中文标题】styled-components:使用额外的样式扩展现有组件【英文标题】:styled-components: Extend existing component with additional prop for styling 【发布时间】:2021-05-16 02:32:26 【问题描述】:我正在使用 styled-components 覆盖现有组件的样式,在本例中是来自 Material ui 的 ToggleButton
。但是我希望我的新组件有一个额外的属性 (hasMargin
) 来控制样式:
import ToggleButton from "@material-ui/lab";
import styled, css from "styled-components";
const StyledToggleButton = styled(ToggleButton)< hasMargin?: boolean >`
&&
color: red;
$props => props.hasMargin &&
css`
margin: 10px;
`
`;
我的意图是StyledToggleButton
的行为与ToggleButton
完全相同,但具有红色,并且可以使用附加属性hasMargin
调用以打开边距css。我想这样称呼它:
<StyledToggleButton
value="" // ToggleButton prop
size="small" // ToggleButton prop
hasMargin=true // My prop from StyledToggleButton
>
click
</StyledToggleButton>
但如果我这样做,在浏览器控制台中我会得到:
Warning: React does not recognize the `hasMargin` prop on a DOM element.
这是因为StyledToggleButton
似乎还将hasMargin
进一步传递给ToggleButton
和ToggleButton
当然不能也不应该处理它(将它传递给没有意义的DOM 元素)。重写我的代码的最佳方法是什么,所以hasMargin
仅由StyledToggleButton
处理?
我创建了一个codesandbox 来说明这个问题。谢谢!
【问题讨论】:
【参考方案1】:这正是transient props 的用途。
您需要做的就是在 prop 前面加上 $
和 styled-components
不会将 prop 传递给底层 DOM 元素。
// Note the $ prefix in the prop name ?
const StyledToggleButton = styled(ToggleButton)< $hasMargin?: boolean >`
&&
color: red;
// Just use the prop as normal
$(props) =>
props.$hasMargin &&
css`
margin: 10px;
`
`;
<StyledToggleButton
value=""
size="small"
/* Assign the prop as normal */
$hasMargin=true
>
click
</StyledToggleButton>;
这是您的updated Codesandbox link,错误消失了。
【讨论】:
太好了,谢谢!这正是我所需要的【参考方案2】:用 span 包裹 ToggleButton 并从那里应用样式怎么样?
const StyledToggleButton = styled.span< hasMargin?: boolean >`
margin: $props => props.hasMargin && '50px';
button
color: red !important;
`
interface MyButtonProps extends ToggleButtonProps
hasMargin?: boolean;
function MyButton(props: MyButtonProps)
const hasMargin, ...toggleButtonProps = props;
return (
<StyledToggleButton hasMargin=hasMargin >
<ToggleButton ...toggleButtonProps>
props.children
</ToggleButton>
</StyledToggleButton>
);
export default function App()
return (
<div className="App">
<MyButton value="">click</MyButton>
<MyButton value="" size="small" hasMargin=true>
click
</MyButton>
</div>
);
【讨论】:
谢谢,这个简单的例子是一个选择。但我真的很想知道如何直接覆盖 ToggleButton。在我的实际项目中,不仅仅是保证金以上是关于styled-components:使用额外的样式扩展现有组件的主要内容,如果未能解决你的问题,请参考以下文章
使用 styled-components 在组件/元素之间共享样式
使用 styled-components 设置 Router Link 的样式
是否可以在 Gatsby 中使用 styled-components 设置 StaticImage 的样式?
使用 styled-components 覆盖 material-ui 按钮样式