Awa Melvine
Awa Melvine

Reputation: 4087

How to render array entries in JSX using map() function with conditional wrapping

I have an array of objects in JavaScript and I want to loop through these objects and return some JSX with bootstrap classes in it such that each row always gets 2 columns displayed inside it.

options: [
  {
    "letter":"A",
    "text": "14 March 1879"
  },
  {
    "letter":"B",
    "text": "14 March 1897"
  },
  {
    "letter":"C",
    "text": "24 May 1879"
  },
  {
    "letter":"D",
    "text": "24 June 1879"
  }
]

In my experience with other languages and template engines, it is pretty simple: You just create an opening and a closing div tag with a class of row and then using your template engine, you loop through and render each object until when the counter of your loop is 2, you dynamically end that role and start a new one.

Something like this:

<div class="row">
    for (var i in options) {
      if(i%2 === 0) {
        <!-- render object ... -->
        </div><!-- then end this row -->
        <div class="row"><!-- start new row -->
      } else {
        <!-- render object -->
      }
    }
</div>

I tried this method inside my map function and it was giving a syntax error because the value returned in the case where the condition passes is not valid JSX.

Thanks for any help.

Edit:

In the End, what I want to achieve is this:

If the array of objects contains 2 objects, I should be able to dynamically display it like this:

 <div class="row">
  <div class="col-md-6">
    <div class="option correct-option">
      A <!-- that is, option.letter -->
    </div>
  </div>
  <div class="col-md-6">
    <div class="option wrong-option">
      B <!-- that is, option.letter -->
    </div>
  </div>
</div>

if the array contains 3 objects, I want to achieve this:

 <div class="row">
  <div class="col-md-6">
    <div class="option correct-option">
      A <!-- that is, option.letter -->
    </div>
  </div>
  <div class="col-md-6">
    <div class="option wrong-option">
      B <!-- that is, option.letter -->
    </div>
  </div>
</div>

<div class="row">
  <div class="col-md-6">
    <div class="option correct-option">
      C <!-- that is, option.letter -->
    </div>
  </div>
</div>

Upvotes: 1

Views: 304

Answers (3)

HTML:

enter image description here

Result:

enter image description here

Validations: Works with: Array.length = 0 & Array.length = n You want 3 Cols?... define a const instead magic number "2"....

Code:

const options = [
  {
    "letter":"A",
    "text": "14 March 1879"
  },
  {
    "letter":"B",
    "text": "14 March 1897"
  },
  {
    "letter":"C",
    "text": "24 May 1879"
  },
];
return (
  <>
    {
      Array.from(Array(Math.round(options.length / 2)).keys()).map((number, index) => {
        return (
          <div className="row">
            {
                options.slice(index * 2, (index * 2) + 2).map(option=>{
                  return (
                    <div className="col-md-6">
                      <div className={`option ${option.true ? 'correct-option' : 'wrong-option'}`}>
                        {option.letter}-{option.text}
                      </div>
                    </div>
                  );
                })
              }
          </div>
        );
      })
    }
  </>
);

Upvotes: 0

Tholle
Tholle

Reputation: 112807

You could use a regular for loop increasing i with 2 every loop, and check if the second option is set to take care of an array of uneven length:

Example

function App() {
  const content = [];

  for (let i = 0; i < options.length; i += 2) {
    content.push(
      <div class="row">
        <div class="col-md-6">
          <div class="option correct-option">{options[i].text}</div>
        </div>
        {options[i + 1] && (
          <div class="col-md-6">
            <div class="option correct-option">{options[i + 1].text}</div>
          </div>
        )}
      </div>
    );
  }

  return <div>{content}</div>;
}

Upvotes: 1

casraf
casraf

Reputation: 21694

How about something like this?

{options.map((option, i) => (
    i % 2 === 0 ? null : ( // skip every 2nd row
      <div class="row">
        A: {option}
        B: {i < options.length ? options[i + 1] : null}
      </div>
    )
)}

Upvotes: 2

Related Questions