I have far too many svg icons to import them all in the recommended way:
import { ReactComponent as Icon } from 'assets/svg/icon.svg'
So in my JS React apps I've been using webpack's require.context
to index the entire svg directory and export it as an object, which then allows me to do this:
import { svg } from 'assets'
function SvgIcon({ icon }) {
const Icon = svg[icon]
return <Icon />
}
/* ... */
<SvgIcon icon='inbox' />
Which is amazing for my use case because I can load all the icons I need dynamically without even having to individually import them. However, as soon as I switched to Typescript, require.context
ceased to use the svg loader. This code, which used to work perfectly before, now only returns { [filename]: "/path/to/filename.39843398.svg" }
, which is what would happen if I didn't use a loader at all. That string is supposed to be a ReactComponent instead.
const assets = context =>
context.keys().reduce((assets: any, path) => {
const key = path.replace(/^\.\//, '').replace(/\..*$/, '')
assets[key] = context(path).default || context(path)
return assets
}, {})
export const svg = assets(require.context('!@svgr/webpack!./svg', false, /\.svg$/))
Codesandbox doesn't seem to support require.context, but you can reproduce this very easily by creating a react app with --template typescript
, installing @svgr/webpack, adding assets/svg, copying the logo.svg there, making an index.ts and copypasterino the codeblocks above.
Depending on your package manager and sdk you may have to fiddle with the config a bit. I had to install @types/webpack-env and add them to tsconfig.json
like so:
{
/* ... */
"types": ["node", "webpack-env"]
}
CodePudding user response:
It turns out the culprit is [email protected]. Downgrading to @4.0.3 fixed the problem.
Incidentally, @5.0.0 had other problems with svg files, like not converting namespace tags to proper JSX. Could be related, could be unrelated.