0

How would you assemble this html using jsx/react. My problem is that i++ is always output as part of the html, although it is something I'd rather want to execute.

const rows = [];

for (let i = 0; i < items.length; i++) {
  let row;
  if (i + 1 < items.length) {
    // on all but the last item we have to items in a row
    row = (
      <div className="bpa-module-tile-row">
        {this.getItem(items[i])}
        i++;
        {this.getItem(items[i])}
        )
      </div>
    );
  } else {
    // if we have an odd number of items, then the last row has only one not two items in a rowj
    row = (
      <div className="bpa-module-tile-row">{this.getItem(items[i])}</div>
    );
  }

  rows.push(row);
}

The rows are then output later using {rows} in jsx. The problem is that the i++ result also ends up in the html. I feel like I am "thinking" or approaching it in a wrong way here.

How can I write this in idiomatic JSX?

3 Answers 3

1

One solution is to increment your counter by 2 and calculate each index as appropriate:

const rows = [];

for (let i = 0; i < items.length; i += 2) {
  let row;
  if (i + 1 < items.length) {
    // on all but the last item we have to items in a row
    row = (
      <div className="bpa-module-tile-row">
        {this.getItem(items[i])}
        {this.getItem(items[i+1])}
        )
      </div>
    );
  } else {
    // if we have an odd number of items, then the last row has only one not two items in a rowj
    row = (
      <div className="bpa-module-tile-row">{this.getItem(items[i])}</div>
    );
  }

  rows.push(row);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, that's the root cause fix, hence cleanest solution. Thanks!
1

You can simple use i++ whereever you want inside the curly braces. Your row object must be like:

row = (
      <div className="bpa-module-tile-row">
        {this.getItem(items[i++])}
        {this.getItem(items[i])}
        )
      </div>
    );

1 Comment

Well, I am not a friend of these "hidden" i++ statements. Really easy to overlook. I'd prefer if the i++ would be a statement on a single line.
1

Array.prototype.map() will iterate through the list and produce another list applying the function you provide it.

Something similar to this is what you're looking for:

const items = [1,2,3,4,5]
const rows = items.map((_, index) => index % 2 ? [] : items.slice(index, index + 2))
  .filter(row => row.length > 0)
  .map(row =>
     (<div className="bpa-module-tile-row">
       {row.map(x => "Item " + x)}
     </div>)
  );

Try it out: JS fiddle


If you can import (or write your own) chunk method then this becomes even more simple:

const rows = chunk(items, size=2)
 .map(row =>
     (<div className="bpa-module-tile-row">
       {row.map(x => "Item " + x)}
     </div>)
  );

7 Comments

I cannot try atm, but why would this not add the index to the row? That's what I want to avoid. Also, I need to process 2 indexes at once unless it is the last and odd index.
I'm a bit confused. You only seem to be maintaining one index in your example. I've edited my answer slightly to try and guess what you're looking for but if you can provide more detail I can help further.
Also what does getItem do? It seems rather confusing to pass an item to that
This will repeat items. The first div will contain the items at indices 0 and 1, the next div will contain items at indices 1 and 2, etc. The original code outputs items at 0 and 1 then items at 2 and 3, etc.
Edited, to avoid the dups.
|

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.