Banjocat
Banjocat

Reputation: 382

How to return multiple list components using react.js

I understand that you can't return multiple elements. But this limitation is causing me to not be able to solve this problem without help.

I am working with an HTML design from another that uses a 1 depth list to represent a 3 depth list. As a last resort I can change this.

An example of the HTML I am converting to React. The number of Devices, cards and remotes could all be different on every GET request.

 <ul class='deviceList'>
   <li>Device A`</li>
   <li>Cards Connected in Device A</li>
   <li>Card 1</li>
   <li>Card 2</li>
   <li>Remotes Connected to Device A</li>
   <li>Remote 1</li>
   <li>Device B</li>
   <li>Cards Connected to Device B</li>
   <li>Card 1</li>
   <!-- ... could go on for more ...-->
 </ul>

This is how I setup the React code that actually contains the <ul>:

var DeviceList = React.createClass({
  render: function() {
    var deviceList = this.props.devices.map(function (device) {
      return [
        <DeviceTitle title='{device.name}' />,
        <ComponentTitle title='Cards' />,
        <Cards cards={device.cards} />,
        <ComponentTitle title='Remotes' />,
        <Remotes remotes={device.remotes} />
      ];
    });

    return (
      <ul className='deviceList'>
        {deviceList}
      </ul>
    );    
  }
});

So the problem is the Card and Remote components need to return multiple list components. I tried having it return an array of list components but this did not work.

Here is what I have .. this is the part that fails.

var cards = React.createClass({
  render: function() {
    var cards = this.props.cards.map(function (card) {
       return (
         <li>{card.name}</li>
       );
    });

    // illegal
    return {{cards});
  }
});

// Remote is a little different but same problem

Also.. to try to make this simpler I only showed a 3 depth list but really it is 4 depths. Each card and remote could have other components attached to them.

So as other questions here have shown. I can't do it this way. So what should I do?

Upvotes: 3

Views: 6735

Answers (3)

Banjocat
Banjocat

Reputation: 382

A solution to solve this. Not saying it is the best but it is the only method I could figure out.

You can use a plain javascript function. Since they have no constraint on what you can return. Then I just used concat on the array that is created for the actual list to add these elements.

function Card(device) {
    return device.cards.map(function(card) {
       return (<li>{card.name}</li>);
    });
}

Upvotes: 0

J. Mark Stevens
J. Mark Stevens

Reputation: 4945

var cards = React.createClass({
  render: function() {
   var cards = this.props.cards.map(function (card) {
     return (
       <li>{card.name}</li>
     );
   };
   return (<ul>{cards}</ul>);
 }
});

Upvotes: 1

Jordan Running
Jordan Running

Reputation: 106027

The problem is that return {{cards}}; isn't valid JavaScript. You only use curly braces like that in JSX. (Also you were missing a closing parenthesis on line 6.) cards is just a regular JavaScript variable, so your function should return it just like any other variable:

var cards = React.createClass({
  render: function() {
    var cards = this.props.cards.map(function (card) {
       return (
         <li>{card.name}</li>
       );
    });

    return <ul>{cards}</ul>;
});

Of course, returning a <ul> instead of an array of <li>s isn't exactly what you wanted, but as a matter of generating sensible markup, it makes sense for Cards and Remotes to be child lists instead of dumping them all into a single list.

Upvotes: 5

Related Questions