【问题标题】:How do I style a material-ui Icon which was passed as prop如何设置作为道具传递的材质 UI 图标
【发布时间】:2020-03-11 17:09:44
【问题描述】:

我正在编写一个自定义 Material UI React 组件,我想将 Icon 作为道具传递给它。但是,我想在获得图标时对其进行样式设置,并将其设为最小宽度和高度。

这是我正在尝试做的简化版本。我想将iconStyle 应用于作为props.statusImage 传入的图标,但不知道如何。

import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/styles";

const useStyles = makeStyles({
  iconStyle: {
    minWidth: 100,
    minHeight: 100
  }
});

function MyComponentWithIconProps(props) {
  const styles = useStyles();

  return <div>{props.statusImage}</div>;
}

MyComponentWithIconProps.propTypes = {
  statusImage: PropTypes.element
};

export default MyComponentWithIconProps;

我使用这样的组件

import {Done} from "@material-ui/icons";
<MyComponentWithIconProps statusImage={<Done/>}

代码沙盒:https://codesandbox.io/s/jovial-fermi-dmb0p

我还尝试将提供的Icon 包装在另一个Icon 元素中并尝试对其进行样式设置。然而,这并没有奏效,而且看起来有点“hacky”。​​

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    主要有三种选择:

    1. 传入图标的元素类型而不是元素(例如Done 而不是&lt;Done/&gt;),然后在渲染元素时添加className(这是分数答案中的方法)。李>
    2. 克隆元素以添加 className 属性。
    3. 在父元素上放置一个类并定位适当的子类型(例如svg)。

    方法一:

    index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import { Done } from "@material-ui/icons";
    import MyComponentWithIconProps from "./MyComponentWithIconProps";
    
    function App() {
      return (
        <div className="App">
          <MyComponentWithIconProps statusImage={Done} />
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    MyComponentWithIconProps.js

    import React from "react";
    import PropTypes from "prop-types";
    import { makeStyles } from "@material-ui/styles";
    
    const useStyles = makeStyles({
      iconStyle: {
        minWidth: 100,
        minHeight: 100
      }
    });
    
    function MyComponentWithIconProps(props) {
      const styles = useStyles();
      const StatusImage = props.statusImage;
      return (
        <div>
          <StatusImage className={styles.iconStyle} />
        </div>
      );
    }
    
    MyComponentWithIconProps.propTypes = {
      statusImage: PropTypes.element
    };
    
    export default MyComponentWithIconProps;
    


    方法二:

    index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import { Done } from "@material-ui/icons";
    import MyComponentWithIconProps from "./MyComponentWithIconProps";
    
    function App() {
      return (
        <div className="App">
          <MyComponentWithIconProps statusImage={<Done />} />
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    MyComponentWithIconProps.js

    import React from "react";
    import PropTypes from "prop-types";
    import { makeStyles } from "@material-ui/styles";
    import clsx from "clsx";
    
    const useStyles = makeStyles({
      iconStyle: {
        minWidth: 100,
        minHeight: 100
      }
    });
    
    function MyComponentWithIconProps(props) {
      const styles = useStyles();
      const styledImage = React.cloneElement(props.statusImage, {
        // Using clsx to combine the new class name with any existing ones that may already be on the element
        className: clsx(styles.iconStyle, props.statusImage.className)
      });
      return <div>{styledImage}</div>;
    }
    
    MyComponentWithIconProps.propTypes = {
      statusImage: PropTypes.element
    };
    
    export default MyComponentWithIconProps;
    


    方法3:

    index.js

    import React from "react";
    import ReactDOM from "react-dom";
    import { Done } from "@material-ui/icons";
    import MyComponentWithIconProps from "./MyComponentWithIconProps";
    
    function App() {
      return (
        <div className="App">
          <MyComponentWithIconProps statusImage={<Done />} />
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    MyComponentWithIconProps.js

    import React from "react";
    import PropTypes from "prop-types";
    import { makeStyles } from "@material-ui/styles";
    
    const useStyles = makeStyles({
      iconStyle: {
        "& > svg": {
          minWidth: 100,
          minHeight: 100
        }
      }
    });
    
    function MyComponentWithIconProps(props) {
      const styles = useStyles();
      return <div className={styles.iconStyle}>{props.statusImage}</div>;
    }
    
    MyComponentWithIconProps.propTypes = {
      statusImage: PropTypes.element
    };
    
    export default MyComponentWithIconProps;
    

    【讨论】:

      【解决方案2】:

      像这样传递图标:

      <MyComponentWithIconProps statusImage={Done} />
      

      然后按如下方式使用:

      return <div><props.statusImage className={styles.iconStyle} /></div>;
      

      【讨论】:

      • 还没有。我现在就试试。
      • 不起作用。我收到以下错误 - Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. at http://localhost:3000/static/js/0.chunk.js:285953:38
      • 检查这个工作示例:codesandbox.io/s/interesting-moser-8why8
      【解决方案3】:

      我会这样做:

      import React from "react";
      import PropTypes from "prop-types";
      import { makeStyles } from "@material-ui/styles";
      
      const useStyles = makeStyles({
        iconStyle: {
          minWidth: 100,
          minHeight: 100,
          color: "red"
        }
      });
      
      function MyComponentWithIconProps(props) {
        const styles = useStyles();
      
        return <div className={styles.iconStyle}>{props.statusImage}</div>;
      }
      
      MyComponentWithIconProps.propTypes = {
        statusImage: PropTypes.element
      };
      
      export default MyComponentWithIconProps;
      

      【讨论】:

      • 这不会设置图标的样式,它只会设置 div 的样式。所以 div 变大了,但 Icon 没有变大。
      【解决方案4】:

      就我而言,这是可行的:

      Index.js

      import {Done} from "@material-ui/icons";
      
      <MyComponentWithIconProps icon={<Done {/*with some props*/}/>}/>
      

      MyComponentWithIconProps.js

      return (<div >{props.icon}</div>); 
      

      CodeSanbox

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-15
        • 2022-01-04
        • 2022-01-10
        • 1970-01-01
        • 2021-01-15
        • 1970-01-01
        • 2021-03-05
        相关资源
        最近更新 更多