The main idea is to only import react material UI icons when it is needed or rather when dynamically where we wouldn't know the icon name at pile time. (Let's gurentee that we would have valid icon names).
My approach was to use a require statment with dynamic path:
const IconComponent = require(`@material-ui/icons/${icon}`).default;
This works fine but some warnings are showing up.
./node_modules/@material-ui/icons/utils/createSvgIcon.d.ts 3:8 Module parse failed: Unexpected token (3:8) You may need an appropriate loader to handle this file type. | import SvgIcon from '@material-ui/core/SvgIcon'; | declare function createSvgIcon(path: React.ReactNode, displayName: string): typeof SvgIcon; | | export default createSvgIcon;
./node_modules/@material-ui/icons/index.d.ts 4:5 Module parse failed: Unexpected token (4:5) You may need an appropriate loader to handle this file type. | import SvgIcon from '@material-ui/core/SvgIcon'; |
type SvgIconComponent = typeof SvgIcon; | | export const AccessAlarm: SvgIconComponent;
My question is: How could we avoid these warnings and do the dynamic import in the appropriate way ?
The main idea is to only import react material UI icons when it is needed or rather when dynamically where we wouldn't know the icon name at pile time. (Let's gurentee that we would have valid icon names).
My approach was to use a require statment with dynamic path:
const IconComponent = require(`@material-ui/icons/${icon}`).default;
This works fine but some warnings are showing up.
./node_modules/@material-ui/icons/utils/createSvgIcon.d.ts 3:8 Module parse failed: Unexpected token (3:8) You may need an appropriate loader to handle this file type. | import SvgIcon from '@material-ui/core/SvgIcon'; | declare function createSvgIcon(path: React.ReactNode, displayName: string): typeof SvgIcon; | | export default createSvgIcon;
./node_modules/@material-ui/icons/index.d.ts 4:5 Module parse failed: Unexpected token (4:5) You may need an appropriate loader to handle this file type. | import SvgIcon from '@material-ui/core/SvgIcon'; |
type SvgIconComponent = typeof SvgIcon; | | export const AccessAlarm: SvgIconComponent;
My question is: How could we avoid these warnings and do the dynamic import in the appropriate way ?
Share Improve this question asked Dec 11, 2020 at 10:14 SoS 777SoS 777 411 silver badge4 bronze badges 2- please provide a snippet with a reproducible situation so we can use it as a starting point. – Renan Souza Commented Dec 12, 2020 at 0:20
- This appears to be a duplicate of another question, where I've posted an answer that may be helpful: stackoverflow./a/77332935 – James Porter Commented Oct 30, 2023 at 10:13
2 Answers
Reset to default 3You can create a hook for this. like the following.
//1) $ npm i string-similarity
import * as icons from '@material-ui/icons'
import stringSimilarity from 'string-similarity'
function useIcons(word) {
const iconsNames = Object.keys(icons)
var matches = stringSimilarity.findBestMatch(word, iconsNames)
const bestMathch = matches.bestMatch.target
const Icon = icons[bestMathch]
return Icon
}
export default useIcons
import Icon from './myCustomeHooks/useIcons'
// other file like
const Icon = useIcons('tablechart') // not the name should start with capital letter in case you use reactjs
// now you can use the icon as you like
<Icon/>
please note: import * as icons from '@material-ui/icons'
is the same as const * as icons = require('@material-ui/icons').default;
option 2
import React from 'react';
import { loadCSS } from 'fg-loadcss';
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
import { green } from '@material-ui/core/colors';
import Icon from '@material-ui/core/Icon';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
'& > .fa': {
margin: theme.spacing(2),
},
},
}),
);
export default function FontAwesome() {
const classes = useStyles();
React.useEffect(() => {
const node = loadCSS(
'https://use.fontawesome./releases/v5.12.0/css/all.css',
document.querySelector('#font-awesome-css'),
);
return () => {
node.parentNode!.removeChild(node);
};
}, []);
return (
<div className={classes.root}>
<Icon className="fa fa-plus-circle" />
<Icon className="fa fa-plus-circle" color="primary" />
<Icon className="fa fa-plus-circle" color="secondary" />
<Icon className="fa fa-plus-circle" style={{ color: green[500] }} />
<Icon className="fa fa-plus-circle" fontSize="small" />
<Icon className="fa fa-plus-circle" style={{ fontSize: 30 }} />
</div>
);
}
first is
(async () => {
if (somethingIsTrue) {
const { default: myDefault, foo, bar } = await
import('/modules/my-module.js');
}
})();
second method is
let module = await import('/modules/my-module.js');
nice working example you can tweak is
const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav > a")) {
link.addEventListener("click", e => {
e.preventDefault();
import('/modules/my-module.js')
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
}