I have this:

map = ranks.map((row, r) => (
  row.map((rank, i) => {
    return [element(r, i, state, rank, toggled, onClick)];
  })
));

It maps through a 2-dimentional array. After each row, I'd like to insert <div class="clearfix"></div>.

I think, if I could somehow get the last index for each row, so I will be able to use it in the row map callback. Can someone show me how to do it?


Try something like:

row.map((rank, i, row) => {
  if (i + 1 === row.length) {
    // Last one.
  } else {
    // Not last one.
  }
})

Old answer:

const rowLen = row.length;
row.map((rank, i) => {
  if (rowLen === i + 1) {
    // last one
  } else {
    // not last one
  }
})

As LeoYuan answered, this is the correct answer, but it can be a bit improved.
map accepts a function with a third parameter, which is the iterated array itself.

row.map((rank, i, arr) => {
    if (arr.length - 1 === i) {
        // last one
    } else {
        // not last one
    }
});

or in a bit shorter version, using an object destructuring (thanks Jose from the comments):

row.map((rank, i, {length}) => {
    if (length - 1 === i) {
        // last one
    } else {
        // not last one
    }
});

Using an arr.length instead of row.length is a better and correct approach for several reasons:

  1. When you mix scopes, it may lead for an unexpected bugs, especially in a poorly written or poorly designed code. In general, it is always a good way to avoid mixing between scopes when possible.

  2. When you like to provide an explicit array, it will work as well. E.g.

    [1,2,3,4].map((rank, i, arr) => {
        if (arr.length - 1 === i) {
            // last one
        } else {
            // not last one
        }
    });
    
  3. If you like to move the callback outside of the map scope (mainly for a better performance), it will be wrong to use row.length as it is out of scope. E.g. in the OP case:

    const mapElement = (rowIndex, state, toggled, onClick) => {
        return (rank, i, arr) => {
            let lastIndex = arr.length - 1;
            return [element(rowIndex, i, state, rank, toggled, onClick, lastIndex)];
        };
    };
    
    map = ranks.map((row, r) => row.map(mapElement(r, state, toggled, onClick)));
    

Fewer lines of code with the same results

row.map((rank, i, {length}) => (

  //last element
  if(i + 1 === length){ 

  }
));