React 无法识别传递给 Material UI 中样式化组件的道具
Posted
技术标签:
【中文标题】React 无法识别传递给 Material UI 中样式化组件的道具【英文标题】:React does not recognize the prop passed to a styled-component within Material UI 【发布时间】:2020-08-12 18:10:19 【问题描述】:样式化组件:
import Typography from '@material-ui/core';
const Text = styled(Typography)<TextProps>`
margin-bottom: 10px;
color: $( textColor ) => textColor ?? textColor;
font-size: $( textSize ) => (textSize ? textSize + 'px' : '16px');
`;
在组件内部使用:
<GlobalStyled.Text textColor="green" textSize="20">test</GlobalStyled.Text>
“警告:React 无法识别 DOM 元素上的 textColor
属性。如果您故意希望它作为自定义属性出现在 DOM 中,请将其拼写为小写 textcolor
。如果您不小心从父组件,将其从 DOM 元素中移除。”
props 被传递给 Typography
组件本身,而不仅仅是 styled-component,如何解决这个问题?
更新
5.1.0 发布的样式化组件:https://github.com/styled-components/styled-components/releases/tag/v5.1.0
现在有新的瞬态道具,通过道具过滤解决了这个问题。您可以在道具名称前使用$propsName
,这是一个美元符号,它将仅传递给样式组件!
【问题讨论】:
错字 -color: $( textColor ) => textColor && textColor;
甚至只是 color: $( textColor ) => textColor;
不是错字,仅供参考:typescriptlang.org/docs/handbook/release-notes/…
谢谢 - 但是,仍然 - 在这里使用它有什么意义?就像你使用$( textColor ) => textColor
【参考方案1】:
你需要得到你不想要的道具,剥掉它们,然后把里面的其余部分传递出去:
const Text = styled( (textColor, textSize, ...rest) => <Typography ...rest/>)<TextProps>`
margin-bottom: 10px;
color: $( textColor ) => textColor ?? textColor;
font-size: $( textSize ) => (textSize ? textSize + "px" : "16px");
`;
这是一个工作示例(没有 TextProps
类型,但它应该可以工作):https://codesandbox.io/s/mui-styled-component-removed-props-rfdjx?file=/src/App.js
这是一个使用 Typescript 的工作示例:
import * as React from "react";
import Typography, TypographyProps from '@material-ui/core/Typography';
import StylesProvider from '@material-ui/core/styles';
import styled from 'styled-components';
interface TextProps extends TypographyProps
textColor: string,
textSize: number
const TypographyWrapper = React.forwardRef<htmlSpanElement, TextProps>(
function TypographyWrapper(textColor, textSize, ...other: TextProps, ref)
return <Typography ...other ref=ref/>
);
const Text = styled(TypographyWrapper)<TextProps>`
margin-bottom: 10px;
color: $( textColor : TextProps) => textColor ?? textColor;
font-size: $( textSize : TextProps) => (textSize ? textSize + 'px' : '16px');
`;
export default function App()
return <StylesProvider injectFirst>
<Text textColor="green">Hello World!</Text>
<Text textColor="red" textSize=30>Hello World!</Text>
</StylesProvider>;
【讨论】:
你知道现在如何正确输入道具吗?我试过 textColor, textSize, ...rest : TextProps
,但由于孩子而引发错误:“类型'孩子:字符串;'与类型没有共同的属性”
@AlexanderKim 我在这个答案中添加了一个 Typescript 示例。
谢谢,我刚刚阅读了 styled-components 5.1.0 发行说明,他们已经实现了瞬态道具:github.com/styled-components/styled-components/releases/tag/…,我刚刚使用了瞬态道具$propsName
,它就起作用了!
@RyanCogswell,仅仅通过自定义 SC 道具看起来工作量太大了,哈哈,我很高兴他们终于推出了这些临时道具。
@AlexanderKim 是的,瞬态道具听起来是一个更好的解决方案。【参考方案2】:
使用version 5.1.0,styled-components 支持瞬态道具。瞬态道具不会传递给组件(即仅在样式中使用),并通过以 $
开头的道具名称来指示。这允许以更简单的方式管理此场景,不再需要包装器组件来删除额外的道具(如 Dekel 的回答)。
import * as React from "react";
import Typography, TypographyProps from "@material-ui/core/Typography";
import StylesProvider from "@material-ui/core/styles";
import styled from "styled-components";
interface TextProps extends TypographyProps
$textColor?: string;
$textSize?: number;
const Text: React.FunctionComponent<TextProps> = styled(Typography)`
margin-bottom: 10px;
color: $( $textColor : TextProps) => $textColor;
font-size: $( $textSize : TextProps) =>
$textSize ? $textSize + "px" : "16px";
`;
export default function App()
return (
<StylesProvider injectFirst>
<Text $textColor="green">Hello World!</Text>
<Text $textColor="red" $textSize=30>
Hello World!
</Text>
</StylesProvider>
);
【讨论】:
【参考方案3】:使用样式组件中的“瞬态道具”
https://styled-components.com/releases
样式化组件
import styled from "styled-components";
import Typography, TypographyProps from "@material-ui/core/Typography";
interface TextProps
$textColor?: string;
$textSize?: number;
export default styled(Typography)<TypographyProps & TextProps>`
margin-bottom: 10px;
color: $(props) => props?.$textColor || 'black';
font-size: $(props) => props?.$textSize ? props?.$textSize +'px' : '16px' !important;
`;
使用
import React from "react";
import render from "react-dom";
import Text from "./components/Text";
function App()
return (
<>
<Text $textColor="blue" $textSize="50" align="center">
text ok
</Text>
</>
);
const rootElement = document.getElementById("root");
render(<App />, rootElement);
https://codesandbox.io/s/react-typescript-transient-styledcomponent-example-eb9uf?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark
<iframe src="https://codesandbox.io/embed/react-typescript-transient-styledcomponent-example-eb9uf?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="react-typescript-transient-styledcomponent-example"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>
【讨论】:
以上是关于React 无法识别传递给 Material UI 中样式化组件的道具的主要内容,如果未能解决你的问题,请参考以下文章
TS 表达式生成的联合类型过于复杂,无法用 Material-UI 和 @react-three/fiber 表示
如何使 Material-UI Dialog 在 React 中工作