How to use svg gracefully in react projects
Background: In the past, svg-sprite-loader was used to process svg files in the vue project. It was very convenient to use. Just load the svg file, configure and define the global components. Recently, I was writing a react project, following the same method, bringing the idea of using svg in vue to In react, the same effect is achieved as long as the svg file is placed in the specified folder and the file name is combined with the react component.
Project environment: create-react-app: 3.0.0 react: 16.8.6 react-router-dom: 5.0.0
project directory
The use steps are as follows:
1. Install svg-sprite-loader
yarn add svg-sprite-loader --dev
or
npm i svg-sprite-loader -D
2. Configure /config/webpack.config.js (configuration after yarn eject)
Note: The newly added loader must be placed before the file-loader
Reason: webpack's loader execution is executed from back to front
Add the following configuration in loader
{
test: /\.(eot|woff2?|ttf|svg)$/,
exclude: path.resolve(__dirname, "../src/icons"), //不处理指定svg的文件(所有使用的svg文件放到该文件夹下)
use: [
{
loader: "url-loader",
options: {
name: "[name]-[hash:5].min.[ext]",
limit: 5000, // fonts file size <= 5KB, use 'base64'; else, output svg file
outputPath: "font",
publicPath: "font"
}
}
]
},
{
test: /\.svg$/,
loader: "svg-sprite-loader",
include: path.resolve(__dirname, "../src/icons"), //只处理指定svg的文件(所有使用的svg文件放到该文件夹下)
options: {
symbolId: "icon-[name]" //symbolId和use使用的名称对应 <use xlinkHref={"#icon-" + iconClass} />
}
},
3. Create a new icons folder under the src folder
Create a new svg folder under the icons folder to put svg files
Directory
index.js loads all svg files in the svg folder
const requireAll = requireContext => requireContext.keys().map(requireContext);
const svgs = require.context("./svg", false, /\.svg$/);
requireAll(svgs);
Then be sure to import src/icons/index.js in the react entry file src/index.js
code show as below
import "./icons";
4. SvgIcon component
Create a SvgIcon folder under the src/components folder and add the index.jsx file
directory
The content of the index.jsx component is as follows:
import React from "react";
import PropTypes from "prop-types";
import styles from "./style.less"; //已启用 CSS Modules
const SvgIcon = props => {
const {
iconClass, fill } = props;
return (
<i aria-hidden="true" className="anticon">
<svg className={
styles["svg-class"]}>
<use xlinkHref={
"#icon-" + iconClass} fill={
fill} />
</svg>
</i>
);
};
SvgIcon.propTypes = {
// svg名字
iconClass: PropTypes.string.isRequired,
// 填充颜色
fill: PropTypes.string
};
SvgIcon.defaultProps = {
fill: "currentColor"
};
export default SvgIcon;
style.less
.svg-class {
display: inline-block;
overflow: hidden;
font-size: 14px;
min-width: 14px;
width: 1em;
height: 1em;
}
5. Use
Put the svg file to be used in the src/icons/svg directory, and give the svg name to iconClass when using it
import React from "react";
import SvgIcon from "@/components/SvgIcon";
const Demo = () => {
const svgName="content" // content.svg 已经放到 /src/icons/svg/ 目录下
return <SvgIcon iconClass={
svgName} />;
};
export default Demo;