【问题标题】:How to override classes using makeStyles and useStyles in material-ui?如何在 material-ui 中使用 makeStyles 和 useStyles 覆盖类?
【发布时间】:2020-08-16 00:19:36
【问题描述】:

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

带样式

使用旧的 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;

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;

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

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

  • 我对如何传递类作为使用 useStyles 覆盖部分类的方法的理解有什么错误?
  • 我应该如何处理它?
  • 如果我使用了错误的方法,为什么当父母有孩子没有的样式时,material-ui 仍然给我一个警告?

    提供给 classes 属性的键 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} />;
}

【问题讨论】:

    标签: css reactjs material-ui overriding


    【解决方案1】:

    使用withStyles 实现此目的的一种方法如下,可以帮助覆盖css 类。

    假设您要覆盖一个名为“.myclass”的类,其中包含"position: absolute;"

    import { withStyles } from '@material-ui/styles';
    
    const styles = {
        "@global": {
          ".myClass": {
            position: "relative", 
          }
       }
    };
    
    const TestComponent = (props) =>  (
         <>
             <SomeComponent {...props}>
         </>
    );    
    
    export default withStyles(styles)(TestComponent);
    

    执行此操作后,您将在&lt;SomeComponent/&gt; 上定义的.myClass 的定义覆盖为"position: relative;"

    【讨论】:

      【解决方案2】:

      在 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/

      【讨论】:

        【解决方案3】:

        withStyles 的功能很少。它几乎只是一个为makeStyles / useStyles 提供 HOC 接口的包装器。所以withStyles 的所有功能仍然可以通过makeStyles 使用。

        你没有得到想要的效果的原因仅仅是因为执行顺序。

        代替:

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

        你应该有:

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

        调用makeStyles 的顺序决定了&lt;head&gt; 中相应样式表的顺序,当specificity 其他方面相同时,该顺序决定了哪些样式胜出(后来的样式胜过早期的样式)。使用withStyles 很难弄错该顺序,因为您用来覆盖其他内容的包装器通常会在它包装的东西之后定义。通过多次调用makeStyles,可以更轻松地执行任意顺序,而不必将覆盖放在它们应该影响的基本样式之后。

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

        相关答案:

        【讨论】:

        • 谢谢!我不知道这实际上是如何覆盖的。我会注意并特别注意调用 makeStyles 的顺序。
        猜你喜欢
        • 2020-04-01
        • 2021-07-28
        • 1970-01-01
        • 2020-04-14
        • 2022-01-06
        • 1970-01-01
        • 2022-01-09
        • 2018-11-22
        • 2020-08-19
        相关资源
        最近更新 更多