Basically, what I want to do is to import an SVG icon to my react component and add props to it. Like size="24px" to make it more flexible as a component. Or make it editable with CSS by adding className prop (so I could add e.g. hover prop to it).
As it's my first time using TypeScript with Webpack, I'm being confused about how should I declare types for SVG element and I get an error (shown below)
As there are many ways of include SVG I decided to import it as a ReactComponent.
menu-icon.svg
<svg width="24" height="24" viewBox="0 0 24 24">
<path fill="currentColor" fillRule="evenodd" d="M4.5 5h15a.5.5 0 1 1 0 1h-15a.5.5 0 0 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1z"></path>
</svg>
header.tsx (here I want my svg icon)
import React from 'react';
import MenuIcon from '../assets/menu-icon.svg';
const Header: React.SFC = () => {
return (
<header className="c-header u-side-paddings">
<MenuIcon className="c-header__icon" /> // <-- className prop doesn't match provided type
</header>
);
};
export default Header;
index.d.ts (so the .svg file can be treated as a component)
declare module '*.svg' {
import React = require('react');
export const ReactComponent: React.SFC<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
Adding className prop to MenuIcon SVG Component causes an error:
(JSX attribute) className: string
Type '{ className: string; }' is not assignable to type 'IntrinsicAttributes'.
Property 'className' does not exist on type 'IntrinsicAttributes'.ts(2322)
My understanding so far
- I could just wrap svg component inside a div, and add a
classNameto it like that:<div className="c-header__icon"><MenuIcon/></div>but I feel like it's an inelegant solution and not really a good practice - I learned from this answer that SVG props aren't strings, cuz they're an
SVGAnimatedStringobjects. So: - I tried to create .tsx file instead of .svg (I wouldn't need
index.d.tsfile then), but it works only ifclassName's type isstring. Also I'm not sure if it's a good practice to store SVG icons in files with different extension that.svg. In my opinion it's not good for clarity. If I'm wrong, tell me what actually good practices are, please. Here's the example:
import React from 'react';
interface MenuIcon {
className?: SVGAnimatedString;
}
export class MenuIcon extends React.PureComponent<MenuIcon> {
render() {
return (
<svg width="24" height="24" viewBox="0 0 24 24">
<path fill="currentColor" fillRule="evenodd" d="M4.5 5h15a.5.5 0 1 1 0 1h-15a.5.5 0 0 1 0-1zm0
6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1zm0 6h15a.5.5 0 1 1 0 1h-15a.5.5 0 1 1 0-1z"></path>
</svg>
);
}
}
I feel like I'm in lack of some basics, It's just really hard for me to figure out what should I focus on, as there are several topics combined

