2

I have an Array of Objects that I'm storing in state with each Object storing values I want to then use to render components:

const activeModal = [
    { modalName: 'dashboard', modal: Dashboard, active: true, icon: DashboardIcon, iconColor: 'black', iconBackground: 'white' },
    { modalName: 'memsline', modal: MEMsLine, active: false, icon: MEMsLineIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'mems', modal: MEMsGrid, active: false, icon: MEMsIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'events', modal: Events, active: false, icon: EventIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'people', modal: People, active: false, icon: PeopleIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'places', modal: Places, active: false, icon: PlaceIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'music', modal: Music, active: false, icon: MusicIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'movies', modal: Movies, active: false, icon: MovieIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'tvshows', modal: TVShows, active: false, icon: TVIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'games', modal: Games, active: false, icon: GameIcon, iconColor: 'white', iconBackground: 'black' },
    { modalName: 'settings', modal: UserSettings, active: false, icon: SettingsIcon, iconColor: 'white', iconBackground: 'black' }
]

I am then creating a constant to store the various Components from the Array as follows:

const displayButtons = this.state.activeModal.map((item, index) =>
    <div key={index}>
        <ListItem button id={item.modalName} style={{ backgroundColor: { item.iconBackground } }}>
            <ListItemIcon>
                <{item.icon} onClick={this.openModal({ item.modalName })} style={{ color: { item.iconColor } }} />,
            </ListItemIcon>,
        </ListItem>
    </div>
)

I can then call the constant {displayButtons} as part of my return. However, this approach currently isn't working.

My code won't compile because there are various parsing errors when return properties from the Array - e.g. item.iconBackground.

What I'm trying to achieve would look like the following for the first object in the Array:

    <div key=0>
        <ListItem button id='dashboard' style={{ backgroundColor: 'white' }}>
            <ListItemIcon>
                <DashboardIcon onClick={this.openModal('dashboard')} style={{ color: 'black' }} />,
            </ListItemIcon>,
        </ListItem>
    </div>

How can I amend my constant to return what I'm after?

4
  • Define "struggling to get this to work." What isn't working? Describe the (various) failure(s). Commented Jul 29, 2020 at 20:10
  • 2
    See the "Choosing the type at runtime" suggestions from React's docs: reactjs.org/docs/jsx-in-depth.html#choosing-the-type-at-runtime Commented Jul 29, 2020 at 20:11
  • I've updated my questions to be more precise with my "struggles"! Commented Jul 29, 2020 at 20:15
  • @Ross - thank you, so instead of using {item.icon} I need to declare a capitalised variable and use that - i.e. const DisplayModalType = item.icon Commented Jul 29, 2020 at 20:19

1 Answer 1

2

You'll have to "unpack" the nested react component into a local variable that has the correct react component name casing, i.e. PascalCase.

const displayButtons = this.state.activeModal.map((item, index) => {
  const Icon = item.icon; // <-- create local variable with proper react component casing

  return (
    <div key={index}>
      <ListItem button id={item.modalName} style={{ backgroundColor: { item.iconBackground } }}>
        <ListItemIcon>
          <Icon // <-- use local "Component"
            onClick={this.openModal({ item.modalName })}
            style={{ color: { item.iconColor } }}
          />
        </ListItemIcon>
      </ListItem>
    </div>
  );
})

You will likely need to do the same with the item.modalName that is passed to the this.openModal callback handler.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.