Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 914
Chris Avatar asked Aug 18 '16 12:08

Chris


3 Answers

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

like image 172
Sandesh K Avatar answered Nov 02 '22 05:11

Sandesh K


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>
  )
}
like image 28
corvid Avatar answered Nov 02 '22 03:11

corvid


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.

like image 22
Felix Kling Avatar answered Nov 02 '22 04:11

Felix Kling