Chris
Chris

Reputation: 1883

Is it possible to loop through an array to dynamically generate react components?

Not sure the title is totally clear (wasn't sure how to phrase it) so let me explain.

I'd like to try and store a list of component names in an array, then loop through using map (or suitable equivalent) in order to display each array value as a JSX component.

So something along the lines of this (appreciate this code doesn't work, just trying to show what I'm hoping to achieve):

render(){
  let links = ['DashboardLink', 'CoursesLink', 'AssignmentsLink'];
  return (
    <div>{
      links.map((Link) => {
        return <Link key={Link} />
      }
    }</div>
  )
}

Ideally the result would be:

<div>
  <DashboardLink key='DashboardLink' />
  <CoursesLink key='CoursesLink' />
  <AssignmentLink key='AssignmentLink' />
</div>

and each component would then render within the div.

I'm very new to React and ES6 so apologies for any glaring mistakes.

Thanks!

Upvotes: 6

Views: 7104

Answers (3)

Felix Kling
Felix Kling

Reputation: 816560

Alternatively, make links an array of functions and use something else key (or the name of the function):

render(){
  let links = [DashboardLink, CoursesLink, AssignmentsLink];
  return (
    <div>{
      links.map((Link, index) => {
        return <Link key={index} />
        // or
        // return React.createElement(Link, {key: index});
      }
    }</div>
  )
}

Your original code doesn't work because React expects Link to resolve to a function, not a string.

Upvotes: 1

corvid
corvid

Reputation: 11187

Why not do something like this?

import CoursesLink from 'components/CoursesLink';
import DashboardLink from 'components/DashboardLink';
import AssignmentsLink from 'components/AssignmentLink';

getComponentByName(name) {
  switch(name):
    case 'DashboardLink':
      return DashboardLink
    case 'AssignmentsLink':
      return AssignmentsLink;
    case 'CoursesLink':
      return CoursesLink;
    default:
      return <div />
}
render() {
  const links = ['DashboardLink', 'AssignmentLink', 'CoursesLink'];
  return (
    <div>
      {links.map(link => React.createElement(getComponentByName(link), key={link}))}
    </div>
  )
}

Upvotes: 1

Sandesh K
Sandesh K

Reputation: 929

You can use a helper function then:

 render(){
   var links = ['DashboardLink', 'CoursesLink', 'AssignmentsLink'];
   var findComponent: function (name){
     switch (name){
         case 'DashboardLink':
             return (<DashboardLink />);
         case 'CoursesLink':
             return (<CoursesLink />);
         case 'AssignmentsLink':
             return (<AssignmentsLink />);
         default:
             return null; //You might want to return something else here//
     }
   }; 
   return (
     <div>
       links.map((Link) => {
         return findComponent(Link);
       }
     </div>
  );
}

You can place this function at other places too...

Use React.createElement method to create custom components: First argument is name of tag, second is a object with properties, and you can add children as third argument.

render(){
   var links = ['DashboardLink', 'CoursesLink', 'AssignmentsLink'];
   return (
     <div>
       links.map((Link) => {
         return React.createElement(Link, {key: Link});
       }
     </div>
  );
}

Refer: https://facebook.github.io/react/docs/glossary.html

Upvotes: 6

Related Questions