首页 > 解决方案 > 如何在 Material UI Select 中使用 SVG 作为 IconComponent?

问题描述

我有

import CaretDownIcon from 'src/../public/images/svg/caret-down.svg';


      <Select
        className={selectClassName}
        data-testid={testId}
        // IconComponent={<SvgIcon>{CaretDownIcon}</SvgIcon>}
        // IconComponent={CaretDownIcon}
        inputProps={{
          name,
          id: labelId,
        }}
        {...rest}
      >

我尝试了这两条评论线,但没有骰子。什么是正确的方法?

标签: reactjssvgmaterial-ui

解决方案


您需要为您的自定义 svg 图标创建一个组件。从 svg 文件中复制路径以制作组件,如下所示:

function CustomSvgIcon(props) {
  return (
    <SvgIcon {...props}>
      <path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
    </SvgIcon>
  );
}

那么你可以将它与IconComponent={CustomSvgIcon}.

这是一个完整的工作示例:

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import SvgIcon from "@material-ui/core/SvgIcon";

const styles = (theme) => ({
  root: {
    display: "flex",
    flexWrap: "wrap"
  },
  formControl: {
    margin: theme.spacing.unit,
    minWidth: 120
  },
  selectEmpty: {
    marginTop: theme.spacing.unit * 2
  }
});
function CustomSvgIcon(props) {
  return (
    <SvgIcon {...props}>
      <path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
    </SvgIcon>
  );
}

class SimpleSelect extends React.Component {
  state = {
    age: "",
    name: "hai"
  };

  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  };

  render() {
    const { classes } = this.props;

    return (
      <form className={classes.root} autoComplete="off">
        <FormControl className={classes.formControl}>
          <InputLabel htmlFor="age-simple">Age</InputLabel>
          <Select
            value={this.state.age}
            onChange={this.handleChange}
            inputProps={{
              name: "age",
              id: "age-simple"
            }}
            IconComponent={CustomSvgIcon}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            <MenuItem value={10}>Ten</MenuItem>
            <MenuItem value={20}>Twenty</MenuItem>
            <MenuItem value={30}>Thirty</MenuItem>
          </Select>
        </FormControl>
      </form>
    );
  }
}

SimpleSelect.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(SimpleSelect);

编辑选择自定义图标

也可以从导入的 SVG 文件创建 React 组件,但这取决于您的构建配置。如果您正在使用,create-react-app那么这将起作用(有关详细信息,请参阅本文)。

下面是使用导入方法的示例。这用于import { ReactComponent as TestSvgAsComponent } from "./test.svg";从 SVG 文件中获取 React 组件。另一个必要的步骤是添加将由 SvgIcon 应用的样式(示例中的classes.iconfrom useIconStyles)。

import React from "react";
import PropTypes from "prop-types";
import { withStyles, makeStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
import { ReactComponent as TestSvgAsComponent } from "./test.svg";
import clsx from "clsx";
const styles = (theme) => ({
  root: {
    display: "flex",
    flexWrap: "wrap"
  },
  formControl: {
    margin: theme.spacing.unit,
    minWidth: 120
  },
  selectEmpty: {
    marginTop: theme.spacing.unit * 2
  }
});
const useIconStyles = makeStyles({
  // This is a copy of the styles from https://github.com/mui-org/material-ui/blob/v4.12.3/packages/material-ui/src/SvgIcon/SvgIcon.js#L10
  icon: {
    fill: "currentColor",
    width: "1em",
    height: "1em",
    display: "inline-block",
    fontSize: "1.5rem",
    transition: "fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms",
    flexShrink: 0,
    userSelect: "none"
  }
});

function CustomSvgIcon({ className, ...other }) {
  const classes = useIconStyles();
  return (
    <TestSvgAsComponent className={clsx(classes.icon, className)} {...other} />
  );
}
class SimpleSelect extends React.Component {
  state = {
    age: "",
    name: "hai"
  };

  handleChange = (event) => {
    this.setState({ [event.target.name]: event.target.value });
  };

  render() {
    const { classes } = this.props;

    return (
      <form className={classes.root} autoComplete="off">
        <FormControl className={classes.formControl}>
          <InputLabel htmlFor="age-simple">Age</InputLabel>
          <Select
            value={this.state.age}
            onChange={this.handleChange}
            inputProps={{
              name: "age",
              id: "age-simple"
            }}
            IconComponent={CustomSvgIcon}
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            <MenuItem value={10}>Ten</MenuItem>
            <MenuItem value={20}>Twenty</MenuItem>
            <MenuItem value={30}>Thirty</MenuItem>
          </Select>
        </FormControl>
      </form>
    );
  }
}

SimpleSelect.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(SimpleSelect);

编辑选择自定义图标

相关文档:

相关答案:


推荐阅读