Material-UI:如何在props中使用传播算子覆盖自定义组件的makeStyles类

时间:2019-08-16 04:40:29

标签: reactjs material-ui

我正在创建一个自定义组件,该组件扩展了Material-UI的Typography组件。

该组件用于我正在创建的模板,因此我想包括覆盖默认类的选项。一个非常基本的指南是provided by Material-UI here,但是当您不能简单地将所有道具传递给useStyles(props)时,它没有提供有关如何执行此操作的详细信息。

我不能将所有props传递给useStyles(props)如下:

  1. 一些道具采用需要定义的默认值
  2. 由于它扩展了Typography组件,因此一些道具被解构(供新的自定义组件使用),而所有其他道具都使用散布运算符传递给Typography组件。
  3. li>
  4. 某些道具仅用于样式设计(即仅作为道具传递给useStyles(props)。如果我将所有道具传递给useStyles(props),则这会导致上述第2点出现问题,因为我无法解构这些仅用于样式的道具,因此它们会作为散布运算符的一部分传递到Typography组件中。

下面是一些说明问题的代码:

// useStyles()

const useStyles = makeStyles(theme => ({
  /** Styles applied to the root element */
  root: (props: StylesProps) => ({
    color: theme.palette.primary.main,
    fontFamily: props.fontFamily,
    fontWeight: props.weight,
    letterSpacing: props.letterSpacing,
    lineHeight: 1,
    textTransform: props.casing
  }),
  /** Styles applied to the second logo text if `name[1] !== undefined` */
  nameEnd: {
    color: theme.palette.secondary.main
  },
  /** Styles applied to the root element if `textShadow=true` */
  textShadow: {
    textShadow: theme.textShadow
  }
}));
// Component

const Logo = React.forwardRef(function Logo(props: LogoProps, ref) {
  const {
    casing = "uppercase", // HAS ISSUES 1, 2 and 3
    className,
    fontFamily, // HAS ISSUES 2 and 3
    letterSpacing, // HAS ISSUES 2 and 3
    name,
    nameSpacing = false,
    textShadow = true, // HAS ISSUES 1, 2 an 3
    weight, // HAS ISSUES 2 and 3
    ...other
  } = props;

  const stylesProps: StylesProps = {
    casing,
    fontFamily,
    letterSpacing,
    weight
  };

  const tiqClasses = useStyles(stylesProps);

  const [nameStart, nameEnd] = name;

  function LogoText(): JSX.Element {
    return (
      <React.Fragment>
        {nameStart}
        {nameSpacing && " "}
        {nameEnd && <span className={tiqClasses.nameEnd}>{nameEnd}</span>}
      </React.Fragment>
    );
  }

  return (
    <Typography
      className={clsx(className, tiqClasses.root, {
        [tiqClasses.nameEnd]: nameEnd,
        [tiqClasses.textShadow]: textShadow
      })}
      component="p"
      ref={ref}
      {...other}
    >
      <LogoText />
    </Typography>
  );
});

如果我将代码更改为:

// Component

const Logo = React.forwardRef(function Logo(props: LogoProps, ref) {
  const {
    className,
    name,
    nameSpacing = false,
    ...other
  } = props;

  const tiqClasses = useStyles(props);

  const [nameStart, nameEnd] = name;

  function LogoText(): JSX.Element {
    return (
      <React.Fragment>
        {nameStart}
        {nameSpacing && " "}
        {nameEnd && <span className={tiqClasses.nameEnd}>{nameEnd}</span>}
      </React.Fragment>
    );
  }

  return (
    <Typography
      className={clsx(className, tiqClasses.root, {
        [tiqClasses.nameEnd]: nameEnd,
        [tiqClasses.textShadow]: textShadow
      })}
      component="p"
      ref={ref}
      {...other}
    >
      <LogoText />
    </Typography>
  );
});

这意味着:

  • casingtextShadow道具不再具有默认值
  • casingfontFamilyletterSpacingweight都被传递到Typography传播运算符下的...other组件,因为它们是不再被破坏。这些不是Typography组件的有效道具,因此它们作为DOM属性被传递下来,由于它们也不是有效的DOM属性,因此也会导致错误。

我要实现的目标

我希望能够通过使用如下组件来覆盖rootnameEndtextShadow类:

<Logo tiqClasses={{ root: "rootOverwriteClass", nameEnd: "nameEndOverwriteClass" }} classes={{ body1: "body1OverwriteClass" }} {...otherProps} />

makeStyles相比,我更愿意withStyles使用tiqClasses

注意:为了澄清,我使用的是classes而不是classes,因为{{1}}已被Material-UI使用。您可以在上面的示例中看到这一点,其中我为每个名称使用了不同的名称。

我该如何实现?

0 个答案:

没有答案