I'm trying to create a custom icon set defined from a css stylesheet but it throws the error " Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <myIcon />
. Did you accidentally export a JSX literal instead of a component? " I don't know why.
In myIcon.jsx, I've created a component myIcon
that renders the custom icon in jsx form. myIconsMap
creates an object map, where each key is the name of the icon and its value is a React component (made from myIcon
).
//myIcon.jsx
import React from 'react';
import 'styles/fonts/customIcons.css';
const myIcons = ['randomIcon1', 'randomIcon2'];
const myIcon = props => {
return <div className={`icon-${props.name}`} />;
};
const myIconsMap = myIcons.reduce((icons, iconName) => {
icons[iconName] = <myIcon name={iconName} />;
return icons;
}, {});
const randomIcon1 = myIconsMap.randomIcon1;
const randomIcon2 = myIconsMap.randomIcon2;
export {randomIcon1, randomIcon2};
But randomIcon1 and randomIcon2 both return typeof object, and I'm confused why because they both reference a React component (ie `). I think this is the problem; I need it to be a typeof function instead of object somehow before the browser can render it correctly.
After, I export my icons from myIcon.jsx to allIcons.jsx. This file is what renders the icons on the browser:
//allIcons.jsx
import {randomIcon1, randomIcon2} from './myIcon';
export const icons = {
randomIcon1,
randomIcon2
}
const Icon = (name) => {
const IconComponent =
icons[`${name.substring(0, 1).toUpperCase()}${name.substring(1)}`];
return <IconComponent />;
};
Anyone have any idea why this is happening?
icons[iconName] = <myIcon name={iconName} />;
This line doesn't create a new component. It renders the existing component, producing a react element. That element is a description of what to put on the page, which looks something like this:
{
$$typeof: Symbol(react.element),
type: MyIcon,
key: null,
ref: null,
props: { name: iconName }
}
It is possible to use this to put stuff on the page, but not with a JSX tag like <IconComponent />
. That would try to render it again, which can't happen since it has already been rendered. To use this element, you'd have to do:
const Icon = (name) => {
const iconElement =
icons[`${name.substring(0, 1).toUpperCase()}${name.substring(1)}`];
return iconElement;
}
The other approach (and the one i'd recommend) is to create separate components for each icon. To do that, you just need to wrap your existing code in a function, thus turning it into a component.
icons[iconName] = () => <myIcon name={iconName} />;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.