3

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?

2
  • 1
    You could try to have only this code in the render function - ` return this.props.cards.map(function (card) { return (<li>{card.name}</li>) });` It should work. Commented Nov 10, 2015 at 17:57
  • I did find a way to do this without resorting to a nested list. I still think that a nested list is the correct way to do it but I did post my answer on the alternative. Commented Nov 10, 2015 at 20:56

3 Answers 3

5

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.

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

2 Comments

Why is more sensible markup the "last resort"? Isn't it better to fix things now, which will be a win for you in terms of maintainability and a win for users in terms of usability, than to bend over backwards to try to accommodate bad markup?
I'm not sure if I agree with that philosophy, but to each their own. I think the best solution, then, is to just output the items as above (with a parent <ul>) and then use CSS to make them appear as though it's the same list. It should be easy. Any other solution is going to either cost you a lot of time and hassle now or at some point in the future.
1

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

1 Comment

While this is what I wanted to avoid. It does seem like the only way.
0

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>);
    });
}

1 Comment

I did end up just wrapping it in <ul> but this did work.

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.