Dynamically create components in React
I am using react-icons and I have a JSON file as follows:
social: {
twitter: {
icon: 'FaTwitter',
link: 'twitterlink',
},
linkedin: {
icon: 'FaLinkedIn',
link: 'linkedinlink',
},
github: {
icon: 'FaGithub',
link: 'githublink',
},
}
I am trying to dynamically create the icons by looping through the JSON, but I'm having a lot of trouble making it work.
Here are snippets of what I've already tried so far along with the outputs and the errors produced in the console:
React Icons import
import * as FontAwesome from 'react-icons/lib/fa';
1
{Object.keys(social).map(key => {
let IconName = Component['FontAwesome.' + social[key].icon];
return (
<li key={key}>
<a href={social[key].link} target="_blank" rel="noopener">
<IconName size="15" />
</a>
</li>
);
})}
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
No output
2
{Object.keys(social).map(key => {
let IconName = FontAwesome`.${social[key].icon}`;
return (
<li key={key}>
<a href={social[key].link} target="_blank" rel="noopener">
<IconName size="15" />
{/* This line produces the same result */}
{/* {React.createElement(IconName, { size: '15' })} */}
</a>
</li>
);
})}
Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_react_icons_lib_fa__
is not a function
No output
3
{Object.keys(social).map(key => {
let IconName = `FontAwesome.${social[key].icon}`;
return (
<li key={key}>
<a href={social[key].link} target="_blank" rel="noopener">
<IconName size="15" />
</a>
</li>
);
})}
Warning: <FontAwesome.FaTwitter />
is using uppercase HTML. Always use lowercase HTML tags in React.
Warning: The tag <FontAwesome.FaTwitter>
is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
There are more errors but for FaLinkedIn
and FaGithub
which are the same.
Output in react dev tool
<li>
<a href="twitterlink" target="_blank" rel="noopener">
<Fontawesome.FaTwitter size="15"></Fontawesome.FaTwitter>
</a>
</li>
HTML output
<li>
<a href="twitterlink" target="_blank" rel="noopener">
<fontawesome.fatwitter size="15"></fontawesome.fatwitter>
</a>
</li>
What I want is something like this:
<FontAwesome.FaTwitter size="15" />
Output in react dev tool
<FaTwitter size="15">
<IconBase viewBox="0 0 40 40" size="15">
<svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="15" width="15" viewBox="0 0 40 40" style="vertical-align: middle;">
<g>
<path d="m37.7 9.1q-1.5 2.2-3.7 3.7 0.1 0.3 0.1 1 0 2.9-0.9 5.8t-2.6 5.5-4.1 4.7-5.7 3.3-7.2 1.2q-6.1 0-11.1-3.3 0.8 0.1 1.7 0.1 5 0 9-3-2.4-0.1-4.2-1.5t-2.6-3.5q0.8 0.1 1.4 0.1 1 0 1.9-0.3-2.5-0.5-4.1-2.5t-1.7-4.6v0q1.5 0.8 3.3 0.9-1.5-1-2.4-2.6t-0.8-3.4q0-2 0.9-3.7 2.7 3.4 6.6 5.4t8.3 2.2q-0.2-0.9-0.2-1.7 0-3 2.1-5.1t5.1-2.1q3.2 0 5.3 2.3 2.4-0.5 4.6-1.7-0.8 2.5-3.2 3.9 2.1-0.2 4.2-1.1z">
</path>
</g>
</svg>
</IconBase>
</FaTwitter>
HTML Output
<svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="15" width="15" viewBox="0 0 40 40" style="vertical-align: middle;">
<g>
<path d="m37.7 9.1q-1.5 2.2-3.7 3.7 0.1 0.3 0.1 1 0 2.9-0.9 5.8t-2.6 5.5-4.1 4.7-5.7 3.3-7.2 1.2q-6.1 0-11.1-3.3 0.8 0.1 1.7 0.1 5 0 9-3-2.4-0.1-4.2-1.5t-2.6-3.5q0.8 0.1 1.4 0.1 1 0 1.9-0.3-2.5-0.5-4.1-2.5t-1.7-4.6v0q1.5 0.8 3.3 0.9-1.5-1-2.4-2.6t-0.8-3.4q0-2 0.9-3.7 2.7 3.4 6.6 5.4t8.3 2.2q-0.2-0.9-0.2-1.7 0-3 2.1-5.1t5.1-2.1q3.2 0 5.3 2.3 2.4-0.5 4.6-1.7-0.8 2.5-3.2 3.9 2.1-0.2 4.2-1.1z">
</path>
</g>
</svg>
Is what I'm trying to do possible? Are there any workarounds or another way of doing it?
There are similar questions are StackOverflow but none seems to be working for me, that's why I asking a new one. I've also tried googling the errors but no luck there either.
Here is how to create react-icons
dynamically given the name of the icon:
import React from "react";
import { render } from "react-dom";
import * as FontAwesome from "react-icons/lib/fa";
const Icon = props => {
const { iconName, size, color } = props;
const icon = React.createElement(FontAwesome[iconName]);
return (
<div style={{ fontSize: size, color: color }}>{icon}</div>
);
};
Once you have this icon wrapper, just use it as a normal React component:
<Icon iconName={"FaBeer"} size={12} color="orange" />
The icon name should follows MixedCaps
naming conversion.
This link is a codesandbox demo of the code above: https://codesandbox.io/s/o715x22m4z
链接地址: http://www.djcxy.com/p/52158.html上一篇: 从HTML字符串渲染React组件
下一篇: 在React中动态创建组件