reactjs 你能把定制的 prop 传递给Material-UI v5 'styled()'组件吗?

wpcxdonn  于 2023-03-12  发布在  React
关注(0)|答案(4)|浏览(157)

例如,在styled-components中可以执行以下操作:

const Div = styled.div`
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};
`;

render(
  <section>
    <Div>Normal</Div>
    <Div primary>Primary</Div>
  </section>
);

使用Material-UI v5 styled实用程序,而不像styled()文档中的示例那样向全局主题对象添加覆盖,是否可以获得相同的结果?

f1tvaqid

f1tvaqid1#

是的!

上述最基本的示例在MUI v5中如下所示:

const Div = styled("div")(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));

render (
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);

但是,正如the React docs所说:
如果您试图使用React无法识别为法律的DOM属性/特性的prop来呈现DOM元素,则会触发unknown-prop警告。您应该确保DOM元素周围没有虚假的prop。
所以MUI给了我们shouldForwardProp选项来告诉MUI是否“应该转发该属性”到根节点。

const Div = styled("div", {
  shouldForwardProp: (prop) => prop !== "primary"
})(({ primary }) => ({
  backgroundColor: primary ? "palevioletred" : "white",
  color: primary ? "white" : "palevioletred"
}));

render (
  <section>
    <Div>Normal</Div>
    <Div primary>Primary!</Div>
  <section>
);
解释

styled函数的第二个参数是一个选项对象,它接受的内容之一是shouldForwardProp,正如文档所说,“指示是否应该将prop转发到组件”。因此,要从控制台中删除未知prop警告,我们告诉它不要用shouldForwardProp: (prop) => prop !== "primary"将自定义属性传递给DOM元素。现在我们在返回自定义样式的函数调用中解构这个属性,并像使用其他函数一样使用这些样式。
如果你也想在这里使用全局theme样式,只要把它和你的自定义 prop 一起解构,比如({ primary, otherProp, thirdProp, theme })
Working codesandbox .
MUI v5 styled API文档

tzxcd3kk

tzxcd3kk2#

下面是一个完整的MUI v5 TypeScript示例,您可以在其中将自定义属性传递给样式化组件:

import React from 'react';
import { Button, styled, Typography } from '@mui/material';

const PREFIX = 'NimbusButton';
const classes = {
    root: `${PREFIX}-root`,
    button: `${PREFIX}-button`
};

interface RootProps {
    textColor?: 'primary' | 'secondary';
    buttonTextColor?: 'primary' | 'secondary';
}

const Root = styled('div', {
    shouldForwardProp: (prop) => prop !== 'textColor' && prop !== 'buttonTextColor',
    name: 'MyThemeComponent',
    slot: 'Root'
})<RootProps>(({ theme, textColor, buttonTextColor }) => ({
    [`& .${classes.root}`]: {
        color: textColor ? theme.palette.primary.main : theme.palette.secondary.main
    },
    [`& .${classes.button}`]: {
        color: buttonTextColor ? theme.palette.primary.main : theme.palette.secondary.main
    }
}));

type OwnProps = {
    textColor: 'primary' | 'secondary';
    buttonTextColor: 'primary' | 'secondary';
    text?: string;
    buttonText: string;
};

const CustomStyledButton: React.FC<OwnProps> = (props) => {
    const { textColor, buttonTextColor, text, buttonText } = props;
    return (
        <Root className={classes.root} textColor={textColor} buttonTextColor={buttonTextColor}>
            {text && <Typography variant={'body1'}>{text}</Typography>}
            <Button className={classes.button}>{buttonText}</Button>
        </Root>
    );
};

export default CustomStyledButton;
ccrfmcuu

ccrfmcuu3#

如果你使用的是TypeScript,我使用的是utility function,所以我总是正确地输入prop名称:

export const shouldForwardProp = <CustomProps extends Record<string, unknown>>(
  props: Array<keyof CustomProps>,
  prop: PropertyKey,
): boolean => !props.includes(prop as string);

const MyComponent = styled('div', {
  shouldForwardProp: (prop) => shouldForwardProp<MyComponentProps>(['isDisabled', 'bgColor'], prop),
})<MyComponentProps>(({ theme, isDisabled, size, bgColor }) => ({
...
t30tvxxf

t30tvxxf4#

这是一个对我有用的代码示例。这个 typescript 示例使用了“@mui/material”中的“styled”和“shouldForwardProp”。我希望这能有所帮助。

import "./styles.css";
import { TextField, styled } from "@mui/material";

interface StyledTextFieldType {
  placeHolderColor: string;
  borderColor: string;
}

const StyledTextField = styled(TextField, {
  shouldForwardProp: (prop) => {
    return prop !== "placeHolderColor" && prop !== "borderColor";
  }
})((prop: StyledTextFieldType) => ({
  input: {
    color: prop.placeHolderColor,
    "&::placeholder": {
      fontStyle: "italic"
    }
  },
  "& .MuiOutlinedInput-root": {
    "& fieldset": {
      borderColor: prop.borderColor,
      borderRadius: "5px"
    }
  }
}));

export default function App() {
  return (
    <div className="App">
      <StyledTextField
        placeHolderColor="green"
        borderColor="red"
        placeholder="Place holder text here.."
        fullWidth
        id="outlined-basic"
        label=""
        variant="outlined"
      />
    </div>
  );
}

这是code sandbox link

相关问题