如何在material-ui中使用makeStyles和useStyles覆盖类?

时间:2020-05-01 13:44:38

标签: css reactjs material-ui overriding

请考虑一个呈现按钮的组件,并说此按钮应具有红色背景和黄色文本颜色。还有一个使用此子级的Parent组件,但说黄色很好,但我希望背景颜色是绿色。

withStyles

使用旧的withStyles没问题。

import React from "react";
import { withStyles } from "@material-ui/core/styles";
import { Button } from "@material-ui/core";

const parentStyles = {
  root: {
    background: "green"
  }
};
const childStyles = {
  root: {
    background: "red"
  },
  label: {
    color: "yellow"
  }
};

const ChildWithStyles = withStyles(childStyles)(({ classes }) => {
  return <Button classes={classes}>Button in Child withStyles</Button>;
});

const ParentWithStyles = withStyles(parentStyles)(({ classes }) => {
  return <ChildWithStyles classes={classes} />;
});


export default ParentWithStyles;

Button in child using withStyles

https://codesandbox.io/s/passing-classes-using-withstyles-w17xs?file=/demo.tsx

makeStyles / useStyles

让我们改用makeStyles / useStyles并遵循material-ui.com上的指南Overriding styles - classes prop

import React from "react";
import { makeStyles } from "@material-ui/styles";
import { Button } from "@material-ui/core";

const parentStyles = {
  root: {
    background: "green"
  }
};
const childStyles = {
  root: {
    background: "red"
  },
  label: {
    color: "yellow"
  }
};

// useStyles variant does NOT let me override classes
const useParentStyles = makeStyles(parentStyles);
const useChildStyles = makeStyles(childStyles);

const ChildUseStyles = ({ classes: classesOverride }) => {
  const classes = useChildStyles({ classes: classesOverride });
  return (
    <>
      <Button classes={classes}>Button1 in Child useStyles</Button>
      <Button classes={classesOverride}>Button2 in Child useStyles</Button>
    </>
  );
};
const AnotherChildUseStyles = props => {
  const classes = useChildStyles(props);
  return (
    <>
      <Button classes={classes}>Button3 in Child useStyles</Button>
    </>
  );
};
const ParentUseStyles = () => {
  const classes = useParentStyles();
  return <>
    <ChildUseStyles classes={classes} />
    <AnotherChildUseStyles classes={classes} />
  </>
};

export default ParentUseStyles;

enter image description here

https://codesandbox.io/s/passing-classes-using-usestyles-6x5hf?file=/demo.tsx

似乎没有办法获得与withStyles相同的效果。有几个问题,考虑到我仍然希望使用某种覆盖类的方法(以前对我来说似乎很有意义)来获得相同的效果(绿色按钮黄色文本)。

  • 对于如何通过使用useStyles覆盖类的一部分的方式,我的理解是错误的?
  • 我应该如何替代呢?
  • 如果我使用了错误的方法,那么当父母拥有孩子所没有的风格时,material-ui为什么仍会警告我?

    提供给class属性的键something在[Child]中未实现

  • 是从旧方法(withStyles)到新方法的移植吗?

顺便说一句,我知道this solution,但是当您要覆盖的内容过多时,这似乎很麻烦。

const useStyles = makeStyles({
  root: {
    backgroundColor: 'red',
    color: props => props.color, // <-- this
  },
});

function MyComponent(props) {
  const classes = useStyles(props);
  return <div className={classes.root} />;
}

2 个答案:

答案 0 :(得分:4)

@Query("SELECT T FROM #{#entityName} T WHERE T.id = :id") Optional<T> getById(@Param("id") Long id); 的功能很少。它几乎是为makeStyles / useStyles提供HOC接口的包装器。因此,withStyles仍然可以使用withStyles的所有功能。

您未获得预期效果的原因仅仅是由于执行顺序。

代替:

makeStyles

您应该拥有:

const useParentStyles = makeStyles(parentStyles);
const useChildStyles = makeStyles(childStyles);

Edit Passing classes using useStyles

调用const useChildStyles = makeStyles(childStyles); const useParentStyles = makeStyles(parentStyles); 的顺序确定makeStyles中相应样式表的顺序,而当specificity相同时,该顺序确定哪种样式获胜(以后的样式赢得较早的样式)。使用<head>很难使该顺序错误,因为通常用来包装其他东西的包装器将在包装东西之后定义。通过多次调用withStyles,可以更轻松地执行一个任意顺序,该顺序不必将覆盖放置在它们应影响的基本样式之后。

理解这一点的关键是要认识到,您实际上并没有传递覆盖,而是将一组新类merged传递给新类。如果makeStyleschildClasses.root === 'child_root_1',则合并结果为parentClasses.root === 'parent_root_1',这意味着将其className设置为mergedClasses.root === 'child_root_1 parent_root_1'的任何元素都将接收两个CSS类。最终结果(就什么覆盖了什么而言)完全取决于两个类中样式的CSS特异性。

相关答案:

答案 1 :(得分:0)

在 Material-ui 4.11.x 中,当使用 ma​​keStyles 创建样式时,使用 createStyles 包裹包围样式,并且此样式的优先级高于默认样式。 >

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    backdrop: {
      zIndex: theme.zIndex.drawer + 1,
      color: '#fff',
    },
  }),
);

您可以尝试删除 createStyles 并查看差异。 来自 https://material-ui.com/components/backdrop/

的代码源