2

I am creating a wrapper component for icons that I import using react-icons. Here is an example of how it looks right now:

import { FaTwitter as Twitter} from 'react-icons/fa'
import { Icon } from './elements 

<Icon>
 <Twitter />
<Icon>

Now, this works just as I want it to -- but I would like to simplify the code. Ideally, I'd like it to look/work like this:

<Icon name='twitter' />

Any idea how to do this?


NOTE: In case it helps, here is current code for my Icon component:

export const Icon = props => <IconBase {...props} />

The <IconBase> component is just some styles from styled-components.


UPDATE

I just want to note that the Twitter example is just that -- an example. I'm looking for a solution that will work no matter what name I pass to the <Icon> component. So, in other words, all of the following (and more) will work:

<Icon name="Facebook" />
<Icon name="Search" />
<Icon name="Menu" />

Each of these would be equivalent to:

<Icon><Facebook /></Icon>
<Icon><Search /></Icon>
<Icon><Menu /></Icon>

In other words, no matter what icon I pull in from react-icons, it will render properly vis-a-vis the name prop.

Moshe
  • 6,011
  • 16
  • 60
  • 112

2 Answers2

1

I think something like this would satisfy your condition.

const App = () => <Icon name="twitter" />;

const dict = { twitter: <Twitter /> };

const Icon = ({ name }) => <IconBase>{dict[name]}</IconBase>;
JohnSnow
  • 444
  • 4
  • 17
  • Thanks for the example. For this method to work, though, I'll need to create a new dictionary entry for each and every icon I want to use -- Facebook, Youtube, MenuIcon, Search Icon, etc? Is there a way to generalize this so that it will automatically work no matter which name I pass in? – Moshe Jun 17 '19 at 19:22
  • Well you can just pass the Component as the name prop and reference it as `{props.name}` inside of your Icon component. But if your constraint is that you want to use `name="{string}"` then I don't think there would be another way. – JohnSnow Jun 17 '19 at 19:26
  • If you want to use a `String` as your prop then you'd have to use the dictionary. If you pass the actual Component, then you don't. You can also use the render prop pattern. ` } />` They are all the same result... – JohnSnow Jun 17 '19 at 19:36
  • Thanks -- in the end, I went for this option: `export const Icon = props => ;`. Which I render as follows: `` – Moshe Jun 17 '19 at 19:49
1

What about this?

// definition:
const Icon = (props) => <SomeIconWrapper><props.glyph /></SomeIconWrapper>;
// usage:
<Icon glyph={Twitter} />

It is super simple and flexible, no need for any dictionary or so.

amik
  • 5,613
  • 3
  • 37
  • 62
  • Yes but in the example he is using a `String` as the prop and not a `Component`. That is the requirement. I thought the whole challenge was converting the string to reference the component. – JohnSnow Jun 17 '19 at 19:27
  • I would rather use a `String`, but I'm open to using a `Component`. – Moshe Jun 17 '19 at 19:36