I have to upgrade antd from v3 to v4, previously we used to show some icons from string passed as prop like this :
<Icon type={props.icon} />
Is there a way to achieve something like this in antd v4 with the new Icon system ? I know the existence of '@ant-design/compatible'
but the migration was made to reduce the bundle size so i'd like to avoid this solution.
Edit : I just changed the way I use icons, in my config file I import the icons and pass them to my generator like this : icon = {props.icon}
instead of the previous <Icon type={props.icon} />
.
All official blocks also support antd@4. Please use it with peace of mind. Due to the deletion of the 4.0 icon, if the icon disappears, please find a suitable replacement in the official website of antd.
If you want to migrate to the new version, you can implement it as described in the above document, but you can set the icon configuration menu icon in Pro, which will not be supported in 4.0, so we provide the corresponding [plugin] (https: / /github.com/umijs/umi-plugin-antd-icon-config) to retain this feature. And set in config.ts
You'll need to install ant-design/icons if you haven't already: Since reason performance on the previous version, antd team was apply tree-shaking to use icon.
For a person who loves early adopters, of course, he must install and upgrade the first time. After consulting the bean paste teacher and getting a promise that the api will not be modified, I have completed the migration in my project. Enjoy the advantages of antd@4 for the first time.
I am using @loadable/component and by created a dynamic component that passes type
File DynamicIcon.js:
import loadable from "@loadable/component";
const DynamicIcon = loadable(props =>
import(`@ant-design/icons/es/icons/${props.type}.js`)
.catch(err => import(`@ant-design/icons/es/icons/WarningOutlined.js`)))
export default DynamicIcon;
And invoke the icon as before v3:
<DynamicIcon type={'TagOutlined'} />
That seems to work
const Icon = ({type, ...rest}) => {
const icons = require(`@ant-design/icons`);
const Component = icons[type];
return <Component {...rest}/>
}
I am here to find a way to dynamically load icon for menu. And I don't like other solution. So I decided to create another solution.
My solution is simple. Actually it is not dynamic, it choose already loaded component. But it is safe for Webpack because it will include only used component in source code. It means result size is smaller than including over 700 count of all svg files in published folder.
// IconSelector.tsx
import React from 'react';
import {
QuestionOutlined,
DashboardOutlined,
SmileOutlined,
FormOutlined,
TabletOutlined,
ProfileOutlined,
CheckCircleOutlined,
WarningOutlined,
UserOutlined,
HighlightOutlined,
TableOutlined,
} from '@ant-design/icons';
interface IconSelectorProps {
type: string;
}
const IconSelector: React.FC<IconSelectorProps> = (props: IconSelectorProps) => {
const Icons = {
QuestionOutlined: <QuestionOutlined />,
DashboardOutlined: <DashboardOutlined />,
SmileOutlined: <SmileOutlined />,
FormOutlined: <FormOutlined />,
TabletOutlined: <TabletOutlined />,
ProfileOutlined: <ProfileOutlined />,
CheckCircleOutlined: <CheckCircleOutlined />,
WarningOutlined: <WarningOutlined />,
UserOutlined: <UserOutlined />,
HighlightOutlined: <HighlightOutlined />,
TableOutlined: <TableOutlined />,
};
const getIcon = (type: string) => {
// Default Icon when not found
let comp = <QuestionOutlined />;
let typeNew = type;
// Default is Outlined when no theme was appended (ex: 'smile')
if (!typeNew.match(/.+(Outlined|Filled|TwoTone)$/i)) {
typeNew += 'Outlined';
}
// If found by key then return value which is component
const found = Object.entries(Icons).find(([k]) => k.toLowerCase() === typeNew.toLowerCase());
if (found) {
[, comp] = found;
}
return comp;
};
return getIcon(props.type);
};
export default IconSelector;
<Menu.Item key="1" icon={menu.icon ? <IconSelector type={menu.icon} /> : null}>
Smile
</Menu>
Or
<Menu.Item key="1">
<IconSelector type="smile" />
<span>Smile</span>
</Menu>
You also can import all the files from antd/icons as:
import * as AntdIcons from '@ant-design/icons';
Then you can access all the available icons from AntdIcons
variable as follows:
const AntdIcon = AntdIcons[iconDetails.render];
Where iconDetails.render
is a variable that is something like HomeOutlined
, SettingsOutlined
etc..
Then finally, you can render your components as
<AntdIcon />
With the help of @Cea's approach, I have managed to set Icons dynamically as shown here:
import * as AntdIcons from '@ant-design/icons';
const CustomIcon=(type:string)=>{
const AntdIcon= AntdIcons[type] // not AntdIcons[iconDetails.render] as @Cea mention;
return <AntdIcon/>
}
Then inside my loop menu, I retrieve the Icon name an pass it to the CustomIcon function as a parameter.
I hope this helps someone
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With