React 无法识别传递给 Material UI 中样式组件的 prop

Ale*_*Kim 11 javascript typescript reactjs material-ui styled-components

样式组件:

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')};
`;
Run Code Online (Sandbox Code Playgroud)

组件内部的用法:

<GlobalStyled.Text textColor="green" textSize="20">test</GlobalStyled.Text>
Run Code Online (Sandbox Code Playgroud)

“警告:React 无法识别textColorDOM 元素上的 prop。如果您故意希望它作为自定义属性出现在 DOM 中,请将其拼写为小写textcolor。如果您不小心从父组件传递了它,请将其从 DOM 中删除元素。”

道具被传递给Typography组件本身,而不仅仅是样式组件,如何解决这个问题?

更新

5.1.0 版本发布的样式组件: https://github.com/styled-components/styled-components/releases/tag/v5.1.0

现在有新的瞬态道具,可以通过道具过滤解决这个问题。您可以在道具名称前使用$propsName, 美元符号,它将仅传递给样式组件!

Dek*_*kel 8

您需要获取不需要的道具,将其剥离,然后传递内部的其余部分:

const Text = styled( ({textColor, textSize, ...rest}) => <Typography {...rest}/>)<TextProps>`
  margin-bottom: 10px;
  color: ${({ textColor }) => textColor ?? textColor};
  font-size: ${({ textSize }) => (textSize ? textSize + "px" : "16px")};
`;
Run Code Online (Sandbox Code Playgroud)

这是一个工作示例(没有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>;
}
Run Code Online (Sandbox Code Playgroud)

编辑删除仅适用于样式组件的道具


小智 7

使用样式组件中的“瞬态道具”

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;
`;
Run Code Online (Sandbox Code Playgroud)

使用

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);
Run Code Online (Sandbox Code Playgroud)

https://codesandbox.io/s/react-typescript-transient-styledcomponent-example-eb9uf?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark

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;
`;
Run Code Online (Sandbox Code Playgroud)


Rya*_*ell 6

在5.1.0 版本中,styled-components 支持瞬态 props。瞬态道具不会传递给组件(即仅在样式中使用),并通过以 开头的道具名称来指示$。这允许以更简单的方式来管理此场景,不再需要包装器组件来删除额外的道具(如 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

编辑删除仅适用于样式组件的道具