Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render the component from property of object?

I am building a navbar which contains few icons and titles.

To build it, I am using react-icons (https://www.npmjs.com/package/react-icons). So, I am importing these items here

import { FaMobileAlt, FaCreditCard, FaRegBuilding } from 'react-icons/fa';

and I have a const responsible for keep the menu items list

const LEFT_MENU_ITEMS = [
  { key: 'devices', icon: FaMobileAlt, title: 'Devices' },
  { key: 'cards', icon: FaCreditCard, title: 'Cards' },
  { key: 'business', icon: FaRegBuilding, title: 'Business' },
];

The normal usage would be something like <FaMobileAlt /> and thats it, but in my case I am trying to iterate over this const to build my list.

buildLeftMenuBar() {
if (!this.props.loggedIn) return null;
return (
  <ul key="leftMenuBar" className="items">
    {_.map(LEFT_MENU_ITEMS, itemDef => (
      <li key={itemDef.key}>
        <NavLink to={`/${itemDef.key}`}>
          <div>
          >>>>>  {itemDef.icon} <<<< 
          </div>
          <span>{itemDef.title}</span>
        </NavLink>
      </li>
    ))}
  </ul>
);

}

The error I get when render the page is

Functions are not valid as a React child. This may happen if you return a Component instead of from render.

So, each icon isnt being rendered. How can I make it work following the same idea ?

ps: It's not only 3 items, I just removed some to make it easier to read the question, thats why I am trying to iterate.

like image 590
vbotio Avatar asked Dec 17 '25 08:12

vbotio


2 Answers

You may use like this:

<itemDef.icon />

Instead of this:

{itemDef.icon}

Or, you may also use like:

{itemDef.icon()}

You might be wondering what's going in here. So, let me explain a little bit:

When you want to render a component say MyComponent, you will be able to print like:

{MyComponent()}

Or,

<MyComponent />

But not like:

{MyComponent}

Because, you will need to call the function. That's it.


As per your comment, you want to supply the size props in the component as you said:

<itemDef.icon size={20} />

And {itemDef.icon()} is not just limited. You can also pass the props here:

{itemDef.icon({size:20})} // component receives size props 20

Though, I would recommend to use <itemDef.icon size={20} /> because it's little bit clear usage.

like image 61
Bhojendra Rauniyar Avatar answered Dec 19 '25 21:12

Bhojendra Rauniyar


You can do it like this:

return(
  <ul key="leftMenuBar" className="items">
     {_.map(LEFT_MENU_ITEMS, item => {
        const Icon = item.icon;
        return (
            <li key={itemDef.key}>
                <NavLink to={`/${itemDef.key}`}>
                   <Icon />
                   <span>{itemDef.title}</span>
                </NavLink>
            </li>
        );
     })}
  </ul>
);
like image 35
Michael Avatar answered Dec 19 '25 21:12

Michael



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!