From this answer from stackoverflow, I got a solution on how to import svg as ReactComponent and change their color/width, etc.
But is it possible to do the same for dynamic import? My functional component:
import * as React from 'react';
import SvgIconComponent from './SvgIcon.Interface';
import {ReactComponent} from '*.svg';
const SvgIcon: React.FC<SvgIconComponent> =({width, color, name}) =>
{
import(`../../assets/icons/${name}.svg`).then((Icon) => {
return <Icon fill={color} width={width}/>
});
};
export default SvgIcon;
In the current implementation I get errors:
TS2749: 'ReactComponent' refers to a value, but is being used as a type here. // .then((Icon as ReactComponent)
TS2604: JSX element type 'Icon' does not have any construct or call signatures. // .then(Icon)
I think it is a better way to use the React component to make the dynamic icons for the color and width.
I add my example code:
export const TwitterIcon = ({color, width}: Props) => (
<svg
width={width ? width : 24}
height={width ? width : 24}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill={color ? color : "#1f1f1f"}
d="M8.0798 19.9998C9.55849 20.0493 11.0321 19.8018 12.4135 19.2721C13.795 18.7424 15.0562 17.9411 16.1227 16.9156C17.1892 15.8901 18.0393 14.6613 18.6228 13.3017C19.2063 11.9421 19.5113 10.4793 19.5198 8.9998C20.1974 8.16121 20.7006 7.19563 20.9998 6.1598C21.0221 6.07796 21.0203 5.99141 20.9946 5.91057C20.9689 5.82974 20.9203 5.75806 20.8548 5.70417C20.7893 5.65027 20.7096 5.61647 20.6253 5.60683C20.5411 5.59718 20.4558 5.6121 20.3798 5.6498C20.0253 5.82045 19.6262 5.87558 19.2386 5.80741C18.8511 5.73923 18.4948 5.5512 18.2198 5.2698C17.8687 4.88538 17.4441 4.57533 16.971 4.35803C16.498 4.14072 15.9861 4.02059 15.4657 4.00473C14.9454 3.98888 14.4272 4.07763 13.9417 4.26574C13.4563 4.45384 13.0136 4.73746 12.6398 5.0998C12.128 5.59546 11.7531 6.21509 11.5516 6.89847C11.3501 7.58186 11.3288 8.30575 11.4898 8.9998C8.1398 9.1998 5.8398 7.6098 3.9998 5.4298C3.94452 5.3672 3.87221 5.32205 3.7917 5.29987C3.71119 5.27769 3.62596 5.27943 3.54642 5.30488C3.46688 5.33033 3.39648 5.37839 3.3438 5.4432C3.29113 5.508 3.25846 5.58674 3.2498 5.6698C2.89927 7.61422 3.15213 9.61935 3.97442 11.4159C4.7967 13.2124 6.14904 14.7143 7.8498 15.7198C6.70943 17.0276 5.10801 17.8445 3.3798 17.9998C3.28721 18.0152 3.20174 18.0591 3.13535 18.1254C3.06896 18.1917 3.02497 18.2772 3.00954 18.3698C2.99411 18.4623 3.00801 18.5574 3.0493 18.6417C3.09059 18.726 3.15719 18.7952 3.2398 18.8398C4.74332 19.5912 6.39903 19.988 8.0798 19.9998Z"
/>
</svg>
);
And if you want to make the icons library
interface IconProps {
keyword: string; //make the clear type to make switch
color: string;
width: number;
}
const SvgIcon = ({keyword, color, width}: IconProps) => {
// In this case you have to think about the switch and types in typescript.
return (
{
'twitter': <TwitterIcon color={color} width={width}/>,
'facebook': <FacebookIcon color={color} width={width}/>,
}[keyword]
)
}
//in component
<SvgIcon keyword='twitter' width={24} color='red'/>
If you have too many SVG icons, I don't have any solution for it on my hands right now. If I have any good idea with it. I will post here again.
import MyIcon from '../../assets/icons/${name}.svg'
<MyIcon />
From what I can see your issue is that you are importing the whole file and trying to render that as a component, you need to append the key / component identifier/const name to the require. For example if you use export defualt YourSVGComponent you can access that dynamically by doing the following;
import * as React from 'react';
import SvgIconComponent from './SvgIcon.Interface';
const SvgIcon: React.FC<SvgIconComponent> =({width, color, name}) =>
{
const Icon = require(`../../assets/icons/${name}.svg`).default
return <Icon fill={color} width={width}/>
};
export default SvgIcon;
I suggest you make use of process.env.PUBLIC_URL to render your svg. Have all your svg files inside public folder, let's say inside public/svgFiles.
you can then use it as
<img src={process.env.PUBLIC_URL + "/svgFiles/" + file_name} alt="project" />
Since everything from the public folder is included in the final build, all your svg files will be taken care of, along with the path you use, since everything will be referred from public folder, path will not be changed after build.